diff --git a/.github/workflows/build-docs.yml b/.github/workflows/build-docs.yml index b3e53b91c..f78b6730e 100644 --- a/.github/workflows/build-docs.yml +++ b/.github/workflows/build-docs.yml @@ -118,7 +118,7 @@ jobs: path: docs/${{ matrix.lang }}/.cache - name: Build Docs run: python ./scripts/docs.py build-lang ${{ matrix.lang }} - - uses: actions/upload-artifact@v4 + - uses: actions/upload-artifact@v5 with: name: docs-site-${{ matrix.lang }} path: ./site/** diff --git a/.github/workflows/deploy-docs.yml b/.github/workflows/deploy-docs.yml index 0eb26cc4d..aa4fd6b65 100644 --- a/.github/workflows/deploy-docs.yml +++ b/.github/workflows/deploy-docs.yml @@ -49,7 +49,7 @@ jobs: run: | rm -rf ./site mkdir ./site - - uses: actions/download-artifact@v5 + - uses: actions/download-artifact@v6 with: path: ./site/ pattern: docs-site-* diff --git a/.github/workflows/issue-manager.yml b/.github/workflows/issue-manager.yml index b587d15e6..f40ec4dc4 100644 --- a/.github/workflows/issue-manager.yml +++ b/.github/workflows/issue-manager.yml @@ -38,7 +38,11 @@ jobs: }, "waiting": { "delay": 2628000, - "message": "As this PR has been waiting for the original user for a while but seems to be inactive, it's now going to be closed. But if there's anyone interested, feel free to create a new PR." + "message": "As this PR has been waiting for the original user for a while but seems to be inactive, it's now going to be closed. But if there's anyone interested, feel free to create a new PR.", + "reminder": { + "before": "P3D", + "message": "Heads-up: this will be closed in 3 days unless there’s new activity." + } }, "invalid": { "delay": 0, diff --git a/.github/workflows/smokeshow.yml b/.github/workflows/smokeshow.yml index e42d79723..eed5fbec0 100644 --- a/.github/workflows/smokeshow.yml +++ b/.github/workflows/smokeshow.yml @@ -34,7 +34,7 @@ jobs: requirements**.txt pyproject.toml - run: uv pip install -r requirements-github-actions.txt - - uses: actions/download-artifact@v5 + - uses: actions/download-artifact@v6 with: name: coverage-html path: htmlcov diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index cbf1a8567..9c3e2218b 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -97,7 +97,7 @@ jobs: COVERAGE_FILE: coverage/.coverage.${{ runner.os }}-py${{ matrix.python-version }} CONTEXT: ${{ runner.os }}-py${{ matrix.python-version }} - name: Store coverage files - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v5 with: name: coverage-${{ matrix.python-version }}-${{ matrix.pydantic-version }} path: coverage @@ -126,7 +126,7 @@ jobs: - name: Install Dependencies run: uv pip install -r requirements-tests.txt - name: Get coverage files - uses: actions/download-artifact@v5 + uses: actions/download-artifact@v6 with: pattern: coverage-* path: coverage @@ -136,7 +136,7 @@ jobs: - run: coverage report - run: coverage html --title "Coverage for ${{ github.sha }}" - name: Store coverage HTML - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v5 with: name: coverage-html path: htmlcov diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 9c075f68e..8e5eba4c4 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -14,7 +14,7 @@ repos: - id: end-of-file-fixer - id: trailing-whitespace - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.13.3 + rev: v0.14.3 hooks: - id: ruff args: diff --git a/README.md b/README.md index a8a0e37b5..09cd38da1 100644 --- a/README.md +++ b/README.md @@ -55,6 +55,7 @@ The key features are: + @@ -125,7 +126,7 @@ If you are building a CLI app to be FastAPI stands on the shoulders of giants: -* Starlette for the web parts. +* Starlette for the web parts. * Pydantic for the data parts. ## Installation @@ -231,7 +232,7 @@ INFO: Application startup complete.
About the command fastapi dev main.py... -The command `fastapi dev` reads your `main.py` file, detects the **FastAPI** app in it, and starts a server using Uvicorn. +The command `fastapi dev` reads your `main.py` file, detects the **FastAPI** app in it, and starts a server using Uvicorn. By default, `fastapi dev` will start with auto-reload enabled for local development. @@ -472,7 +473,7 @@ Used by Starlette: Used by FastAPI: -* uvicorn - for the server that loads and serves your application. This includes `uvicorn[standard]`, which includes some dependencies (e.g. `uvloop`) needed for high performance serving. +* uvicorn - for the server that loads and serves your application. This includes `uvicorn[standard]`, which includes some dependencies (e.g. `uvloop`) needed for high performance serving. * `fastapi-cli[standard]` - to provide the `fastapi` command. * This includes `fastapi-cloud-cli`, which allows you to deploy your FastAPI application to FastAPI Cloud. diff --git a/docs/de/docs/_llm-test.md b/docs/de/docs/_llm-test.md index 4a5e5392c..72846ef06 100644 --- a/docs/de/docs/_llm-test.md +++ b/docs/de/docs/_llm-test.md @@ -47,7 +47,7 @@ Das LLM wird dies wahrscheinlich falsch übersetzen. Interessant ist nur, ob es //// tab | Info -Der Prompt-Designer kann entscheiden, ob neutrale Anführungszeichen in typografische Anführungszeichen umgewandelt werden sollen. Es ist in Ordnung, sie unverändert zu lassen. +Der Promptdesigner kann entscheiden, ob neutrale Anführungszeichen in typografische Anführungszeichen umgewandelt werden sollen. Es ist in Ordnung, sie unverändert zu lassen. Siehe zum Beispiel den Abschnitt `### Quotes` in `docs/de/llm-prompt.md`. @@ -459,7 +459,7 @@ Für einige sprachspezifische Anweisungen, siehe z. B. den Abschnitt `### Headin * der Commit * der Contextmanager * die Coroutine -* die Datenbank-Session +* die Datenbanksession * die Festplatte * die Domain * die Engine @@ -496,7 +496,7 @@ Für einige sprachspezifische Anweisungen, siehe z. B. den Abschnitt `### Headin //// tab | Info -Dies ist eine nicht vollständige und nicht normative Liste von (meist) technischen Begriffen, die in der Dokumentation vorkommen. Sie kann dem Prompt-Designer helfen herauszufinden, bei welchen Begriffen das LLM Unterstützung braucht. Zum Beispiel, wenn es eine gute Übersetzung immer wieder auf eine suboptimale Übersetzung zurücksetzt. Oder wenn es Probleme hat, einen Begriff in Ihrer Sprache zu konjugieren/deklinieren. +Dies ist eine nicht vollständige und nicht normative Liste von (meist) technischen Begriffen, die in der Dokumentation vorkommen. Sie kann dem Promptdesigner helfen herauszufinden, bei welchen Begriffen das LLM Unterstützung braucht. Zum Beispiel, wenn es eine gute Übersetzung immer wieder auf eine suboptimale Übersetzung zurücksetzt. Oder wenn es Probleme hat, einen Begriff in Ihrer Sprache zu konjugieren/deklinieren. Siehe z. B. den Abschnitt `### List of English terms and their preferred German translations` in `docs/de/llm-prompt.md`. diff --git a/docs/de/docs/advanced/events.md b/docs/de/docs/advanced/events.md index 2ceef1190..f94526b4f 100644 --- a/docs/de/docs/advanced/events.md +++ b/docs/de/docs/advanced/events.md @@ -154,7 +154,7 @@ In der technischen ASGI-Spezifikation ist dies Teil des Starlettes Lifespan-Dokumentation. +Weitere Informationen zu Starlettes `lifespan`-Handlern finden Sie in Starlettes Lifespan-Dokumentation. Einschließlich, wie man Lifespan-Zustand handhabt, der in anderen Bereichen Ihres Codes verwendet werden kann. diff --git a/docs/de/docs/advanced/middleware.md b/docs/de/docs/advanced/middleware.md index 0a2a39699..8396a626b 100644 --- a/docs/de/docs/advanced/middleware.md +++ b/docs/de/docs/advanced/middleware.md @@ -94,4 +94,4 @@ Zum Beispiel: * Uvicorns `ProxyHeadersMiddleware` * MessagePack -Um mehr über weitere verfügbare Middlewares herauszufinden, besuchen Sie Starlettes Middleware-Dokumentation und die ASGI Awesome List. +Um mehr über weitere verfügbare Middlewares herauszufinden, besuchen Sie Starlettes Middleware-Dokumentation und die ASGI Awesome List. diff --git a/docs/de/docs/advanced/response-cookies.md b/docs/de/docs/advanced/response-cookies.md index 0dd4175dd..02fe99c26 100644 --- a/docs/de/docs/advanced/response-cookies.md +++ b/docs/de/docs/advanced/response-cookies.md @@ -48,4 +48,4 @@ Und da die `Response` häufig zum Setzen von Headern und Cookies verwendet wird, /// -Um alle verfügbaren Parameter und Optionen anzuzeigen, sehen Sie sich deren Dokumentation in Starlette an. +Um alle verfügbaren Parameter und Optionen anzuzeigen, sehen Sie sich deren Dokumentation in Starlette an. diff --git a/docs/de/docs/advanced/response-headers.md b/docs/de/docs/advanced/response-headers.md index a5e310d55..1dc7c0691 100644 --- a/docs/de/docs/advanced/response-headers.md +++ b/docs/de/docs/advanced/response-headers.md @@ -38,4 +38,4 @@ Und da die `Response` häufig zum Setzen von Headern und Cookies verwendet wird, Beachten Sie, dass benutzerdefinierte proprietäre Header mittels des Präfix `X-` hinzugefügt werden können. -Wenn Sie jedoch benutzerdefinierte Header haben, die ein Client in einem Browser sehen können soll, müssen Sie diese zu Ihrer CORS-Konfiguration hinzufügen (weitere Informationen finden Sie unter [CORS (Cross-Origin Resource Sharing)](../tutorial/cors.md){.internal-link target=_blank}), unter Verwendung des Parameters `expose_headers`, dokumentiert in Starlettes CORS-Dokumentation. +Wenn Sie jedoch benutzerdefinierte Header haben, die ein Client in einem Browser sehen können soll, müssen Sie diese zu Ihrer CORS-Konfiguration hinzufügen (weitere Informationen finden Sie unter [CORS (Cross-Origin Resource Sharing)](../tutorial/cors.md){.internal-link target=_blank}), unter Verwendung des Parameters `expose_headers`, dokumentiert in Starlettes CORS-Dokumentation. diff --git a/docs/de/docs/advanced/templates.md b/docs/de/docs/advanced/templates.md index fdaeb3413..65c7998b8 100644 --- a/docs/de/docs/advanced/templates.md +++ b/docs/de/docs/advanced/templates.md @@ -123,4 +123,4 @@ Und da Sie `StaticFiles` verwenden, wird diese CSS-Datei automatisch von Ihrer * ## Mehr Details { #more-details } -Weitere Informationen, einschließlich, wie man Templates testet, finden Sie in Starlettes Dokumentation zu Templates. +Weitere Informationen, einschließlich, wie man Templates testet, finden Sie in Starlettes Dokumentation zu Templates. diff --git a/docs/de/docs/advanced/testing-events.md b/docs/de/docs/advanced/testing-events.md index 1a68b7714..569518c51 100644 --- a/docs/de/docs/advanced/testing-events.md +++ b/docs/de/docs/advanced/testing-events.md @@ -5,7 +5,7 @@ Wenn Sie `lifespan` in Ihren Tests ausführen müssen, können Sie den `TestClie {* ../../docs_src/app_testing/tutorial004.py hl[9:15,18,27:28,30:32,41:43] *} -Sie können mehr Details unter [„Lifespan in Tests ausführen in der offiziellen Starlette-Dokumentation.“](https://www.starlette.io/lifespan/#running-lifespan-in-tests) nachlesen. +Sie können mehr Details unter [„Lifespan in Tests ausführen in der offiziellen Starlette-Dokumentation.“](https://www.starlette.dev/lifespan/#running-lifespan-in-tests) nachlesen. Für die deprecateten Events `startup` und `shutdown` können Sie den `TestClient` wie folgt verwenden: diff --git a/docs/de/docs/advanced/testing-websockets.md b/docs/de/docs/advanced/testing-websockets.md index a71310cbf..f25aa4fd0 100644 --- a/docs/de/docs/advanced/testing-websockets.md +++ b/docs/de/docs/advanced/testing-websockets.md @@ -8,6 +8,6 @@ Dazu verwenden Sie den `TestClient` in einer `with`-Anweisung, eine Verbindung z /// note | Hinweis -Weitere Informationen finden Sie in Starlettes Dokumentation zum Testen von WebSockets. +Weitere Informationen finden Sie in Starlettes Dokumentation zum Testen von WebSockets. /// diff --git a/docs/de/docs/advanced/using-request-directly.md b/docs/de/docs/advanced/using-request-directly.md index 7782237ec..8ec6741d0 100644 --- a/docs/de/docs/advanced/using-request-directly.md +++ b/docs/de/docs/advanced/using-request-directly.md @@ -15,7 +15,7 @@ Es gibt jedoch Situationen, in denen Sie möglicherweise direkt auf das `Request ## Details zum `Request`-Objekt { #details-about-the-request-object } -Da **FastAPI** unter der Haube eigentlich **Starlette** ist, mit einer Ebene von mehreren Tools darüber, können Sie Starlettes `Request`-Objekt direkt verwenden, wenn Sie es benötigen. +Da **FastAPI** unter der Haube eigentlich **Starlette** ist, mit einer Ebene von mehreren Tools darüber, können Sie Starlettes `Request`-Objekt direkt verwenden, wenn Sie es benötigen. Das bedeutet allerdings auch, dass, wenn Sie Daten direkt vom `Request`-Objekt nehmen (z. B. dessen Body lesen), diese von FastAPI nicht validiert, konvertiert oder dokumentiert werden (mit OpenAPI, für die automatische API-Benutzeroberfläche). @@ -45,7 +45,7 @@ Auf die gleiche Weise können Sie wie gewohnt jeden anderen Parameter deklariere ## `Request`-Dokumentation { #request-documentation } -Weitere Details zum `Request`-Objekt finden Sie in der offiziellen Starlette-Dokumentation. +Weitere Details zum `Request`-Objekt finden Sie in der offiziellen Starlette-Dokumentation. /// note | Technische Details diff --git a/docs/de/docs/advanced/websockets.md b/docs/de/docs/advanced/websockets.md index ad1f6f5b1..5f662770f 100644 --- a/docs/de/docs/advanced/websockets.md +++ b/docs/de/docs/advanced/websockets.md @@ -182,5 +182,5 @@ Wenn Sie etwas benötigen, das sich leicht in FastAPI integrieren lässt, aber r Weitere Informationen zu Optionen finden Sie in der Dokumentation von Starlette: -* Die `WebSocket`-Klasse. -* Klassen-basierte Handhabung von WebSockets. +* Die `WebSocket`-Klasse. +* Klassen-basierte Handhabung von WebSockets. diff --git a/docs/de/docs/alternatives.md b/docs/de/docs/alternatives.md index 15c0719fb..4dd127dba 100644 --- a/docs/de/docs/alternatives.md +++ b/docs/de/docs/alternatives.md @@ -417,7 +417,7 @@ Die gesamte Datenvalidierung, Datenserialisierung und automatische Modelldokumen /// -### Starlette { #starlette } +### Starlette { #starlette } Starlette ist ein leichtgewichtiges ASGI-Framework/Toolkit, welches sich ideal für die Erstellung hochperformanter asynchroner Dienste eignet. @@ -462,7 +462,7 @@ Alles, was Sie also mit Starlette machen können, können Sie direkt mit **FastA /// -### Uvicorn { #uvicorn } +### Uvicorn { #uvicorn } Uvicorn ist ein blitzschneller ASGI-Server, der auf uvloop und httptools basiert. diff --git a/docs/de/docs/deployment/manually.md b/docs/de/docs/deployment/manually.md index 6393f8ebc..2de2913a5 100644 --- a/docs/de/docs/deployment/manually.md +++ b/docs/de/docs/deployment/manually.md @@ -52,7 +52,7 @@ Das Wichtigste, was Sie benötigen, um eine **FastAPI**-Anwendung (oder eine and Es gibt mehrere Alternativen, einschließlich: -* Uvicorn: ein hochperformanter ASGI-Server. +* Uvicorn: ein hochperformanter ASGI-Server. * Hypercorn: ein ASGI-Server, der unter anderem kompatibel mit HTTP/2 und Trio ist. * Daphne: der für Django Channels entwickelte ASGI-Server. * Granian: Ein Rust HTTP-Server für Python-Anwendungen. diff --git a/docs/de/docs/fastapi-cli.md b/docs/de/docs/fastapi-cli.md index d41ed598e..ab9c8373e 100644 --- a/docs/de/docs/fastapi-cli.md +++ b/docs/de/docs/fastapi-cli.md @@ -52,7 +52,7 @@ FastAPI CLI nimmt den Pfad zu Ihrem Python-Programm (z. B. `main.py`), erkennt a Für die Produktion würden Sie stattdessen `fastapi run` verwenden. 🚀 -Intern verwendet das **FastAPI CLI** Uvicorn, einen leistungsstarken, produktionsreifen, ASGI-Server. 😎 +Intern verwendet das **FastAPI CLI** Uvicorn, einen leistungsstarken, produktionsreifen, ASGI-Server. 😎 ## `fastapi dev` { #fastapi-dev } diff --git a/docs/de/docs/features.md b/docs/de/docs/features.md index c52f6733e..0b51e9737 100644 --- a/docs/de/docs/features.md +++ b/docs/de/docs/features.md @@ -159,7 +159,7 @@ Jede Integration wurde so entworfen, dass sie so einfach zu nutzen ist (mit Abh ## Starlette Merkmale { #starlette-features } -**FastAPI** ist vollkommen kompatibel (und basiert auf) Starlette. Das bedeutet, wenn Sie eigenen Starlette Quellcode haben, funktioniert der. +**FastAPI** ist vollkommen kompatibel (und basiert auf) Starlette. Das bedeutet, wenn Sie eigenen Starlette Quellcode haben, funktioniert der. `FastAPI` ist tatsächlich eine Unterklasse von `Starlette`. Wenn Sie also bereits Starlette kennen oder benutzen, das meiste funktioniert genau so. diff --git a/docs/de/docs/history-design-future.md b/docs/de/docs/history-design-future.md index 40a7a8286..45198ff1c 100644 --- a/docs/de/docs/history-design-future.md +++ b/docs/de/docs/history-design-future.md @@ -58,7 +58,7 @@ Nachdem ich mehrere Alternativen getestet hatte, entschied ich, dass ich **Starlette** beigetragen, der anderen Schlüsselanforderung. +Während der Entwicklung habe ich auch zu **Starlette** beigetragen, der anderen Schlüsselanforderung. ## Entwicklung { #development } diff --git a/docs/de/docs/how-to/custom-request-and-route.md b/docs/de/docs/how-to/custom-request-and-route.md index 41a85f832..246717c04 100644 --- a/docs/de/docs/how-to/custom-request-and-route.md +++ b/docs/de/docs/how-to/custom-request-and-route.md @@ -66,7 +66,7 @@ Das `scope`-`dict` und die `receive`-Funktion sind beide Teil der ASGI-Spezifika Und diese beiden Dinge, `scope` und `receive`, werden benötigt, um eine neue `Request`-Instanz zu erstellen. -Um mehr über den `Request` zu erfahren, schauen Sie sich Starlettes Dokumentation zu Requests an. +Um mehr über den `Request` zu erfahren, schauen Sie sich Starlettes Dokumentation zu Requests an. /// diff --git a/docs/de/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md b/docs/de/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md new file mode 100644 index 000000000..7f60492ee --- /dev/null +++ b/docs/de/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md @@ -0,0 +1,133 @@ +# Von Pydantic v1 zu Pydantic v2 migrieren { #migrate-from-pydantic-v1-to-pydantic-v2 } + +Wenn Sie eine ältere FastAPI-App haben, nutzen Sie möglicherweise Pydantic Version 1. + +FastAPI unterstützt seit Version 0.100.0 sowohl Pydantic v1 als auch v2. + +Wenn Sie Pydantic v2 installiert hatten, wurde dieses verwendet. Wenn stattdessen Pydantic v1 installiert war, wurde jenes verwendet. + +Pydantic v1 ist jetzt deprecatet und die Unterstützung dafür wird in den nächsten Versionen von FastAPI entfernt, Sie sollten also zu **Pydantic v2 migrieren**. Auf diese Weise erhalten Sie die neuesten Features, Verbesserungen und Fixes. + +/// warning | Achtung + +Außerdem hat das Pydantic-Team die Unterstützung für Pydantic v1 in den neuesten Python-Versionen eingestellt, beginnend mit **Python 3.14**. + +Wenn Sie die neuesten Features von Python nutzen möchten, müssen Sie sicherstellen, dass Sie Pydantic v2 verwenden. + +/// + +Wenn Sie eine ältere FastAPI-App mit Pydantic v1 haben, zeige ich Ihnen hier, wie Sie sie zu Pydantic v2 migrieren, und die **neuen Features in FastAPI 0.119.0**, die Ihnen bei einer schrittweisen Migration helfen. + +## Offizieller Leitfaden { #official-guide } + +Pydantic hat einen offiziellen Migrationsleitfaden von v1 zu v2. + +Er enthält auch, was sich geändert hat, wie Validierungen nun korrekter und strikter sind, mögliche Stolpersteine, usw. + +Sie können ihn lesen, um besser zu verstehen, was sich geändert hat. + +## Tests { #tests } + +Stellen Sie sicher, dass Sie [Tests](../tutorial/testing.md){.internal-link target=_blank} für Ihre App haben und diese in Continuous Integration (CI) ausführen. + +Auf diese Weise können Sie das Update durchführen und sicherstellen, dass weiterhin alles wie erwartet funktioniert. + +## `bump-pydantic` { #bump-pydantic } + +In vielen Fällen, wenn Sie reguläre Pydantic-Modelle ohne Anpassungen verwenden, können Sie den Großteil des Prozesses der Migration von Pydantic v1 auf Pydantic v2 automatisieren. + +Sie können `bump-pydantic` vom selben Pydantic-Team verwenden. + +Dieses Tool hilft Ihnen, den Großteil des zu ändernden Codes automatisch anzupassen. + +Danach können Sie die Tests ausführen und prüfen, ob alles funktioniert. Falls ja, sind Sie fertig. 😎 + +## Pydantic v1 in v2 { #pydantic-v1-in-v2 } + +Pydantic v2 enthält alles aus Pydantic v1 als Untermodul `pydantic.v1`. + +Das bedeutet, Sie können die neueste Version von Pydantic v2 installieren und die alten Pydantic‑v1‑Komponenten aus diesem Untermodul importieren und verwenden, als hätten Sie das alte Pydantic v1 installiert. + +{* ../../docs_src/pydantic_v1_in_v2/tutorial001_an_py310.py hl[1,4] *} + +### FastAPI-Unterstützung für Pydantic v1 in v2 { #fastapi-support-for-pydantic-v1-in-v2 } + +Seit FastAPI 0.119.0 gibt es außerdem eine teilweise Unterstützung für Pydantic v1 innerhalb von Pydantic v2, um die Migration auf v2 zu erleichtern. + +Sie könnten also Pydantic auf die neueste Version 2 aktualisieren und die Importe so ändern, dass das Untermodul `pydantic.v1` verwendet wird, und in vielen Fällen würde es einfach funktionieren. + +{* ../../docs_src/pydantic_v1_in_v2/tutorial002_an_py310.py hl[2,5,15] *} + +/// warning | Achtung + +Beachten Sie, dass, da das Pydantic‑Team Pydantic v1 in neueren Python‑Versionen nicht mehr unterstützt, beginnend mit Python 3.14, auch die Verwendung von `pydantic.v1` unter Python 3.14 und höher nicht unterstützt wird. + +/// + +### Pydantic v1 und v2 in derselben App { #pydantic-v1-and-v2-on-the-same-app } + +Es wird von Pydantic **nicht unterstützt**, dass ein Pydantic‑v2‑Modell Felder hat, die als Pydantic‑v1‑Modelle definiert sind, und umgekehrt. + +```mermaid +graph TB + subgraph "❌ Nicht unterstützt" + direction TB + subgraph V2["Pydantic-v2-Modell"] + V1Field["Pydantic-v1-Modell"] + end + subgraph V1["Pydantic-v1-Modell"] + V2Field["Pydantic-v2-Modell"] + end + end + + style V2 fill:#f9fff3 + style V1 fill:#fff6f0 + style V1Field fill:#fff6f0 + style V2Field fill:#f9fff3 +``` + +... aber Sie können getrennte Modelle, die Pydantic v1 bzw. v2 nutzen, in derselben App verwenden. + +```mermaid +graph TB + subgraph "✅ Unterstützt" + direction TB + subgraph V2["Pydantic-v2-Modell"] + V2Field["Pydantic-v2-Modell"] + end + subgraph V1["Pydantic-v1-Modell"] + V1Field["Pydantic-v1-Modell"] + end + end + + style V2 fill:#f9fff3 + style V1 fill:#fff6f0 + style V1Field fill:#fff6f0 + style V2Field fill:#f9fff3 +``` + +In einigen Fällen ist es sogar möglich, sowohl Pydantic‑v1‑ als auch Pydantic‑v2‑Modelle in derselben **Pfadoperation** Ihrer FastAPI‑App zu verwenden: + +{* ../../docs_src/pydantic_v1_in_v2/tutorial003_an_py310.py hl[2:3,6,12,21:22] *} + +Im obigen Beispiel ist das Eingabemodell ein Pydantic‑v1‑Modell, und das Ausgabemodell (definiert in `response_model=ItemV2`) ist ein Pydantic‑v2‑Modell. + +### Pydantic v1 Parameter { #pydantic-v1-parameters } + +Wenn Sie einige der FastAPI-spezifischen Tools für Parameter wie `Body`, `Query`, `Form`, usw. zusammen mit Pydantic‑v1‑Modellen verwenden müssen, können Sie die aus `fastapi.temp_pydantic_v1_params` importieren, während Sie die Migration zu Pydantic v2 abschließen: + +{* ../../docs_src/pydantic_v1_in_v2/tutorial004_an_py310.py hl[4,18] *} + +### In Schritten migrieren { #migrate-in-steps } + +/// tip | Tipp + +Probieren Sie zuerst `bump-pydantic` aus. Wenn Ihre Tests erfolgreich sind und das funktioniert, sind Sie mit einem einzigen Befehl fertig. ✨ + +/// + +Wenn `bump-pydantic` für Ihren Anwendungsfall nicht funktioniert, können Sie die Unterstützung für Pydantic‑v1‑ und Pydantic‑v2‑Modelle in derselben App nutzen, um die Migration zu Pydantic v2 schrittweise durchzuführen. + +Sie könnten zuerst Pydantic auf die neueste Version 2 aktualisieren und die Importe so ändern, dass für all Ihre Modelle `pydantic.v1` verwendet wird. + +Anschließend können Sie beginnen, Ihre Modelle gruppenweise von Pydantic v1 auf v2 zu migrieren – in kleinen, schrittweisen Etappen. 🚶 diff --git a/docs/de/docs/index.md b/docs/de/docs/index.md index edcb61b94..4be65071b 100644 --- a/docs/de/docs/index.md +++ b/docs/de/docs/index.md @@ -123,7 +123,7 @@ Wenn Sie eine Starlette für die Webanteile. +* Starlette für die Webanteile. * Pydantic für die Datenanteile. ## Installation { #installation } @@ -229,7 +229,7 @@ INFO: Application startup complete.
Was der Befehl fastapi dev main.py macht ... -Der Befehl `fastapi dev` liest Ihre `main.py`-Datei, erkennt die **FastAPI**-App darin und startet einen Server mit Uvicorn. +Der Befehl `fastapi dev` liest Ihre `main.py`-Datei, erkennt die **FastAPI**-App darin und startet einen Server mit Uvicorn. Standardmäßig wird `fastapi dev` mit aktiviertem Auto-Reload für die lokale Entwicklung gestartet. @@ -470,7 +470,7 @@ Verwendet von Starlette: Verwendet von FastAPI: -* uvicorn – für den Server, der Ihre Anwendung lädt und bereitstellt. Dies umfasst `uvicorn[standard]`, das einige Abhängigkeiten (z. B. `uvloop`) beinhaltet, die für eine Bereitstellung mit hoher Performanz benötigt werden. +* uvicorn – für den Server, der Ihre Anwendung lädt und bereitstellt. Dies umfasst `uvicorn[standard]`, das einige Abhängigkeiten (z. B. `uvloop`) beinhaltet, die für eine Bereitstellung mit hoher Performanz benötigt werden. * `fastapi-cli[standard]` – um den `fastapi`-Befehl bereitzustellen. * Dies beinhaltet `fastapi-cloud-cli`, das es Ihnen ermöglicht, Ihre FastAPI-Anwendung auf FastAPI Cloud bereitzustellen. diff --git a/docs/de/docs/tutorial/background-tasks.md b/docs/de/docs/tutorial/background-tasks.md index ea85207ce..2c381ccfa 100644 --- a/docs/de/docs/tutorial/background-tasks.md +++ b/docs/de/docs/tutorial/background-tasks.md @@ -63,7 +63,7 @@ Und dann schreibt ein weiterer Hintergrundtask, der in der *Pfadoperation-Funkti ## Technische Details { #technical-details } -Die Klasse `BackgroundTasks` stammt direkt von `starlette.background`. +Die Klasse `BackgroundTasks` stammt direkt von `starlette.background`. Sie wird direkt in FastAPI importiert/inkludiert, sodass Sie sie von `fastapi` importieren können und vermeiden, versehentlich das alternative `BackgroundTask` (ohne das `s` am Ende) von `starlette.background` zu importieren. @@ -71,7 +71,7 @@ Indem Sie nur `BackgroundTasks` (und nicht `BackgroundTask`) verwenden, ist es d Es ist immer noch möglich, `BackgroundTask` allein in FastAPI zu verwenden, aber Sie müssen das Objekt in Ihrem Code erstellen und eine Starlette-`Response` zurückgeben, die es enthält. -Weitere Details finden Sie in Starlettes offizieller Dokumentation für Hintergrundtasks. +Weitere Details finden Sie in Starlettes offizieller Dokumentation für Hintergrundtasks. ## Vorbehalt { #caveat } diff --git a/docs/de/docs/tutorial/first-steps.md b/docs/de/docs/tutorial/first-steps.md index 374127c17..7ec98c53b 100644 --- a/docs/de/docs/tutorial/first-steps.md +++ b/docs/de/docs/tutorial/first-steps.md @@ -155,7 +155,7 @@ Ebenfalls können Sie es verwenden, um automatisch Code für Clients zu generier `FastAPI` ist eine Klasse, die direkt von `Starlette` erbt. -Sie können alle Starlette-Funktionalitäten auch mit `FastAPI` nutzen. +Sie können alle Starlette-Funktionalitäten auch mit `FastAPI` nutzen. /// diff --git a/docs/de/docs/tutorial/handling-errors.md b/docs/de/docs/tutorial/handling-errors.md index 51294f44f..58e4607c5 100644 --- a/docs/de/docs/tutorial/handling-errors.md +++ b/docs/de/docs/tutorial/handling-errors.md @@ -81,7 +81,7 @@ Aber falls Sie es für ein fortgeschrittenes Szenario benötigen, können Sie be ## Benutzerdefinierte Exceptionhandler installieren { #install-custom-exception-handlers } -Sie können benutzerdefinierte Exceptionhandler mit den gleichen Exception-Werkzeugen von Starlette hinzufügen. +Sie können benutzerdefinierte Exceptionhandler mit den gleichen Exception-Werkzeugen von Starlette hinzufügen. Angenommen, Sie haben eine benutzerdefinierte Exception `UnicornException`, die Sie (oder eine Bibliothek, die Sie verwenden) `raise`n könnten. diff --git a/docs/de/docs/tutorial/middleware.md b/docs/de/docs/tutorial/middleware.md index a1e2ba9df..6410deba1 100644 --- a/docs/de/docs/tutorial/middleware.md +++ b/docs/de/docs/tutorial/middleware.md @@ -37,7 +37,7 @@ Die Middleware-Funktion erhält: Beachten Sie, dass benutzerdefinierte proprietäre Header hinzugefügt werden können unter Verwendung des `X-`-Präfixes. -Wenn Sie jedoch benutzerdefinierte Header haben, die ein Client in einem Browser sehen soll, müssen Sie sie zu Ihrer CORS-Konfiguration ([CORS (Cross-Origin Resource Sharing)](cors.md){.internal-link target=_blank}) hinzufügen, indem Sie den Parameter `expose_headers` verwenden, der in der Starlettes CORS-Dokumentation dokumentiert ist. +Wenn Sie jedoch benutzerdefinierte Header haben, die ein Client in einem Browser sehen soll, müssen Sie sie zu Ihrer CORS-Konfiguration ([CORS (Cross-Origin Resource Sharing)](cors.md){.internal-link target=_blank}) hinzufügen, indem Sie den Parameter `expose_headers` verwenden, der in der Starlettes CORS-Dokumentation dokumentiert ist. /// diff --git a/docs/de/docs/tutorial/static-files.md b/docs/de/docs/tutorial/static-files.md index 5a6cfcb2b..0c4e7c8ab 100644 --- a/docs/de/docs/tutorial/static-files.md +++ b/docs/de/docs/tutorial/static-files.md @@ -37,4 +37,4 @@ Alle diese Parameter können anders als „`static`“ lauten, passen Sie sie an ## Weitere Informationen { #more-info } -Weitere Details und Optionen finden Sie in der Dokumentation von Starlette zu statischen Dateien. +Weitere Details und Optionen finden Sie in der Dokumentation von Starlette zu statischen Dateien. diff --git a/docs/de/docs/tutorial/testing.md b/docs/de/docs/tutorial/testing.md index 75ee9fade..9c28a2a22 100644 --- a/docs/de/docs/tutorial/testing.md +++ b/docs/de/docs/tutorial/testing.md @@ -1,6 +1,6 @@ # Testen { #testing } -Dank Starlette ist das Testen von **FastAPI**-Anwendungen einfach und macht Spaß. +Dank Starlette ist das Testen von **FastAPI**-Anwendungen einfach und macht Spaß. Es basiert auf HTTPX, welches wiederum auf der Grundlage von Requests konzipiert wurde, es ist also sehr vertraut und intuitiv. diff --git a/docs/de/llm-prompt.md b/docs/de/llm-prompt.md index 23c111d2d..df202d2ff 100644 --- a/docs/de/llm-prompt.md +++ b/docs/de/llm-prompt.md @@ -185,7 +185,7 @@ Example: # FastAPI in Containern - Docker { #fastapi-in-containers-docker } »»» -3.1) Do not apply rule 3 when there is no space before or no space after the dash. +3.1) Do not apply rule 3 when there is no space before or no space after the hyphen. Example: @@ -195,13 +195,13 @@ Example: ## Type hints and annotations { #type-hints-and-annotations } »»» - Translate with (German) – use a short dash: + Translate with (German) – notice the hyphen: ««« ## Typhinweise und -annotationen { #type-hints-and-annotations } »»» - Do NOT translate with (German): + Do NOT translate with (German) – notice the dash: ««« ## Typhinweise und –annotationen { #type-hints-and-annotations } @@ -222,7 +222,7 @@ Ich versuche nicht, alles einzudeutschen. Das bezieht sich besonders auf Begriff ### List of English terms and their preferred German translations -Below is a list of English terms and their preferred German translations, separated by a colon («:»). Use these translations, do not use your own. If an existing translation does not use these terms, update it to use them. A term or a translation may be followed by an explanation in brackets, which explains when to translate the term this way. If a translation is preceded by «NOT», then that means: do NOT use this translation for this term. English nouns, starting with the word «the», have the German genus – «der», «die», «das» – prepended to their German translation, to help you to grammatically decline them in the translation. They are given in singular case, unless they have «(plural)» attached, which means they are given in plural case. Verbs are given in the full infinitive – starting with the word «to». +Below is a list of English terms and their preferred German translations, separated by a colon («:»). Use these translations, do not use your own. If an existing translation does not use these terms, update it to use them. In the below list, a term or a translation may be followed by an explanation in brackets, which explains when to translate the term this way. If a translation is preceded by «NOT», then that means: do NOT use this translation for this term. English nouns, starting with the word «the», have the German genus – «der», «die», «das» – prepended to their German translation, to help you to grammatically decline them in the translation. They are given in singular case, unless they have «(plural)» attached, which means they are given in plural case. Verbs are given in the full infinitive – starting with the word «to». * «/// check»: «/// check | Testen» * «/// danger»: «/// danger | Gefahr» diff --git a/docs/em/docs/advanced/events.md b/docs/em/docs/advanced/events.md index 68adb6d65..dcaac710e 100644 --- a/docs/em/docs/advanced/events.md +++ b/docs/em/docs/advanced/events.md @@ -140,7 +140,7 @@ async with lifespan(app): /// info -👆 💪 ✍ 🌅 🔃 👫 🎉 🐕‍🦺 💃 🎉' 🩺. +👆 💪 ✍ 🌅 🔃 👫 🎉 🐕‍🦺 💃 🎉' 🩺. /// diff --git a/docs/em/docs/advanced/middleware.md b/docs/em/docs/advanced/middleware.md index cb04fa3fb..22d707062 100644 --- a/docs/em/docs/advanced/middleware.md +++ b/docs/em/docs/advanced/middleware.md @@ -92,4 +92,4 @@ app.add_middleware(UnicornMiddleware, some_config="rainbow") * Uvicorn `ProxyHeadersMiddleware` * 🇸🇲 -👀 🎏 💪 🛠️ ✅ 💃 🛠️ 🩺 & 🔫 👌 📇. +👀 🎏 💪 🛠️ ✅ 💃 🛠️ 🩺 & 🔫 👌 📇. diff --git a/docs/em/docs/advanced/response-cookies.md b/docs/em/docs/advanced/response-cookies.md index d9fdbaa87..a6e37ad74 100644 --- a/docs/em/docs/advanced/response-cookies.md +++ b/docs/em/docs/advanced/response-cookies.md @@ -48,4 +48,4 @@ /// -👀 🌐 💪 🔢 & 🎛, ✅ 🧾 💃. +👀 🌐 💪 🔢 & 🎛, ✅ 🧾 💃. diff --git a/docs/em/docs/advanced/response-headers.md b/docs/em/docs/advanced/response-headers.md index e9e1b62d2..c255380d6 100644 --- a/docs/em/docs/advanced/response-headers.md +++ b/docs/em/docs/advanced/response-headers.md @@ -38,4 +38,4 @@ ✔️ 🤯 👈 🛃 © 🎚 💪 🚮 ⚙️ '✖-' 🔡. -✋️ 🚥 👆 ✔️ 🛃 🎚 👈 👆 💚 👩‍💻 🖥 💪 👀, 👆 💪 🚮 👫 👆 ⚜ 📳 (✍ 🌅 [⚜ (✖️-🇨🇳 ℹ 🤝)](../tutorial/cors.md){.internal-link target=_blank}), ⚙️ 🔢 `expose_headers` 📄 💃 ⚜ 🩺. +✋️ 🚥 👆 ✔️ 🛃 🎚 👈 👆 💚 👩‍💻 🖥 💪 👀, 👆 💪 🚮 👫 👆 ⚜ 📳 (✍ 🌅 [⚜ (✖️-🇨🇳 ℹ 🤝)](../tutorial/cors.md){.internal-link target=_blank}), ⚙️ 🔢 `expose_headers` 📄 💃 ⚜ 🩺. diff --git a/docs/em/docs/advanced/templates.md b/docs/em/docs/advanced/templates.md index ad4d4fc71..2e8f56228 100644 --- a/docs/em/docs/advanced/templates.md +++ b/docs/em/docs/advanced/templates.md @@ -81,4 +81,4 @@ $ pip install jinja2 ## 🌅 ℹ -🌅 ℹ, 🔌 ❔ 💯 📄, ✅ 💃 🩺 🔛 📄. +🌅 ℹ, 🔌 ❔ 💯 📄, ✅ 💃 🩺 🔛 📄. diff --git a/docs/em/docs/advanced/testing-websockets.md b/docs/em/docs/advanced/testing-websockets.md index 2a01de629..96aa8b765 100644 --- a/docs/em/docs/advanced/testing-websockets.md +++ b/docs/em/docs/advanced/testing-websockets.md @@ -8,6 +8,6 @@ /// note -🌅 ℹ, ✅ 💃 🧾 🔬 *️⃣ . +🌅 ℹ, ✅ 💃 🧾 🔬 *️⃣ . /// diff --git a/docs/em/docs/advanced/using-request-directly.md b/docs/em/docs/advanced/using-request-directly.md index 9530d49bc..238557e5e 100644 --- a/docs/em/docs/advanced/using-request-directly.md +++ b/docs/em/docs/advanced/using-request-directly.md @@ -15,7 +15,7 @@ ## ℹ 🔃 `Request` 🎚 -**FastAPI** 🤙 **💃** 🔘, ⏮️ 🧽 📚 🧰 🔛 🔝, 👆 💪 ⚙️ 💃 `Request` 🎚 🔗 🕐❔ 👆 💪. +**FastAPI** 🤙 **💃** 🔘, ⏮️ 🧽 📚 🧰 🔛 🔝, 👆 💪 ⚙️ 💃 `Request` 🎚 🔗 🕐❔ 👆 💪. ⚫️ 🔜 ⛓ 👈 🚥 👆 🤚 📊 ⚪️➡️ `Request` 🎚 🔗 (🖼, ✍ 💪) ⚫️ 🏆 🚫 ✔, 🗜 ⚖️ 📄 (⏮️ 🗄, 🏧 🛠️ 👩‍💻 🔢) FastAPI. @@ -45,7 +45,7 @@ ## `Request` 🧾 -👆 💪 ✍ 🌅 ℹ 🔃 `Request` 🎚 🛂 💃 🧾 🕸. +👆 💪 ✍ 🌅 ℹ 🔃 `Request` 🎚 🛂 💃 🧾 🕸. /// note | 📡 ℹ diff --git a/docs/em/docs/advanced/websockets.md b/docs/em/docs/advanced/websockets.md index cc6e5c5f0..a097778c7 100644 --- a/docs/em/docs/advanced/websockets.md +++ b/docs/em/docs/advanced/websockets.md @@ -182,5 +182,5 @@ Client #1596980209979 left the chat 💡 🌅 🔃 🎛, ✅ 💃 🧾: -* `WebSocket` 🎓. -* 🎓-⚓️ *️⃣ 🚚. +* `WebSocket` 🎓. +* 🎓-⚓️ *️⃣ 🚚. diff --git a/docs/em/docs/alternatives.md b/docs/em/docs/alternatives.md index 59b587285..4cbac7539 100644 --- a/docs/em/docs/alternatives.md +++ b/docs/em/docs/alternatives.md @@ -417,7 +417,7 @@ Pydantic 🗃 🔬 💽 🔬, 🛠️ & 🧾 (⚙️ 🎻 🔗) ⚓️ 🔛 /// -### 💃 +### 💃 💃 💿 🔫 🛠️/🧰, ❔ 💯 🏗 ↕-🎭 ✳ 🐕‍🦺. @@ -462,7 +462,7 @@ Pydantic 🗃 🔬 💽 🔬, 🛠️ & 🧾 (⚙️ 🎻 🔗) ⚓️ 🔛 /// -### Uvicorn +### Uvicorn Uvicorn 🌩-⏩ 🔫 💽, 🏗 🔛 uvloop & httptool. diff --git a/docs/em/docs/deployment/manually.md b/docs/em/docs/deployment/manually.md index 8ebe00c7c..4fa2d13e2 100644 --- a/docs/em/docs/deployment/manually.md +++ b/docs/em/docs/deployment/manually.md @@ -4,7 +4,7 @@ 📤 3️⃣ 👑 🎛: -* Uvicorn: ↕ 🎭 🔫 💽. +* Uvicorn: ↕ 🎭 🔫 💽. * Hypercorn: 🔫 💽 🔗 ⏮️ 🇺🇸🔍/2️⃣ & 🎻 👪 🎏 ⚒. * 👸: 🔫 💽 🏗 ✳ 📻. @@ -24,7 +24,7 @@ //// tab | Uvicorn -* Uvicorn, 🌩-⏩ 🔫 💽, 🏗 🔛 uvloop & httptool. +* Uvicorn, 🌩-⏩ 🔫 💽, 🏗 🔛 uvloop & httptool.
diff --git a/docs/em/docs/features.md b/docs/em/docs/features.md index 13cafa72f..ccbed0cae 100644 --- a/docs/em/docs/features.md +++ b/docs/em/docs/features.md @@ -159,7 +159,7 @@ FastAPI 🔌 📶 ⏩ ⚙️, ✋️ 📶 🏋️ . -✋️ 🚥 👆 ✔️ 🛃 🎚 👈 👆 💚 👩‍💻 🖥 💪 👀, 👆 💪 🚮 👫 👆 ⚜ 📳 ([⚜ (✖️-🇨🇳 ℹ 🤝)](cors.md){.internal-link target=_blank}) ⚙️ 🔢 `expose_headers` 📄 💃 ⚜ 🩺. +✋️ 🚥 👆 ✔️ 🛃 🎚 👈 👆 💚 👩‍💻 🖥 💪 👀, 👆 💪 🚮 👫 👆 ⚜ 📳 ([⚜ (✖️-🇨🇳 ℹ 🤝)](cors.md){.internal-link target=_blank}) ⚙️ 🔢 `expose_headers` 📄 💃 ⚜ 🩺. /// diff --git a/docs/em/docs/tutorial/static-files.md b/docs/em/docs/tutorial/static-files.md index 6ff6e37a9..27685c06d 100644 --- a/docs/em/docs/tutorial/static-files.md +++ b/docs/em/docs/tutorial/static-files.md @@ -37,4 +37,4 @@ ## 🌅 ℹ -🌖 ℹ & 🎛 ✅ 💃 🩺 🔃 🎻 📁. +🌖 ℹ & 🎛 ✅ 💃 🩺 🔃 🎻 📁. diff --git a/docs/em/docs/tutorial/testing.md b/docs/em/docs/tutorial/testing.md index cb4a1ca21..2e4a531f7 100644 --- a/docs/em/docs/tutorial/testing.md +++ b/docs/em/docs/tutorial/testing.md @@ -1,6 +1,6 @@ # 🔬 -👏 💃, 🔬 **FastAPI** 🈸 ⏩ & 😌. +👏 💃, 🔬 **FastAPI** 🈸 ⏩ & 😌. ⚫️ ⚓️ 🔛 🇸🇲, ❔ 🔄 🏗 ⚓️ 🔛 📨, ⚫️ 📶 😰 & 🏋️. diff --git a/docs/en/data/contributors.yml b/docs/en/data/contributors.yml index c892d8baf..592c79af0 100644 --- a/docs/en/data/contributors.yml +++ b/docs/en/data/contributors.yml @@ -1,11 +1,11 @@ tiangolo: login: tiangolo - count: 782 + count: 794 avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4 url: https://github.com/tiangolo dependabot: login: dependabot - count: 117 + count: 126 avatarUrl: https://avatars.githubusercontent.com/in/29110?v=4 url: https://github.com/apps/dependabot alejsdev: @@ -15,7 +15,7 @@ alejsdev: url: https://github.com/alejsdev pre-commit-ci: login: pre-commit-ci - count: 45 + count: 49 avatarUrl: https://avatars.githubusercontent.com/in/68672?v=4 url: https://github.com/apps/pre-commit-ci github-actions: @@ -25,7 +25,7 @@ github-actions: url: https://github.com/apps/github-actions Kludex: login: Kludex - count: 24 + count: 25 avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=df8a3f06ba8f55ae1967a3e2d5ed882903a4e330&v=4 url: https://github.com/Kludex dmontagu: @@ -33,36 +33,36 @@ dmontagu: count: 17 avatarUrl: https://avatars.githubusercontent.com/u/35119617?u=540f30c937a6450812628b9592a1dfe91bbe148e&v=4 url: https://github.com/dmontagu +YuriiMotov: + login: YuriiMotov + count: 15 + avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=b9b13d598dddfab529a52d264df80a900bfe7060&v=4 + url: https://github.com/YuriiMotov +nilslindemann: + login: nilslindemann + count: 14 + avatarUrl: https://avatars.githubusercontent.com/u/6892179?u=1dca6a22195d6cd1ab20737c0e19a4c55d639472&v=4 + url: https://github.com/nilslindemann euri10: login: euri10 count: 13 avatarUrl: https://avatars.githubusercontent.com/u/1104190?u=321a2e953e6645a7d09b732786c7a8061e0f8a8b&v=4 url: https://github.com/euri10 -nilslindemann: - login: nilslindemann +svlandeg: + login: svlandeg count: 13 - avatarUrl: https://avatars.githubusercontent.com/u/6892179?u=1dca6a22195d6cd1ab20737c0e19a4c55d639472&v=4 - url: https://github.com/nilslindemann + avatarUrl: https://avatars.githubusercontent.com/u/8796347?u=556c97650c27021911b0b9447ec55e75987b0e8a&v=4 + url: https://github.com/svlandeg kantandane: login: kantandane count: 13 avatarUrl: https://avatars.githubusercontent.com/u/3978368?u=cccc199291f991a73b1ebba5abc735a948e0bd16&v=4 url: https://github.com/kantandane -svlandeg: - login: svlandeg - count: 11 - avatarUrl: https://avatars.githubusercontent.com/u/8796347?u=556c97650c27021911b0b9447ec55e75987b0e8a&v=4 - url: https://github.com/svlandeg zhaohan-dong: login: zhaohan-dong count: 11 avatarUrl: https://avatars.githubusercontent.com/u/65422392?u=8260f8781f50248410ebfa4c9bf70e143fe5c9f2&v=4 url: https://github.com/zhaohan-dong -YuriiMotov: - login: YuriiMotov - count: 10 - avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=b9b13d598dddfab529a52d264df80a900bfe7060&v=4 - url: https://github.com/YuriiMotov mariacamilagl: login: mariacamilagl count: 9 @@ -158,6 +158,11 @@ prostomarkeloff: count: 3 avatarUrl: https://avatars.githubusercontent.com/u/28061158?u=6918e39a1224194ba636e897461a02a20126d7ad&v=4 url: https://github.com/prostomarkeloff +frankie567: + login: frankie567 + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/1144727?u=f3e79acfe4ed207e15c2145161a8a9759925fcd2&v=4 + url: https://github.com/frankie567 nsidnev: login: nsidnev count: 3 @@ -191,7 +196,7 @@ Serrones: uriyyo: login: uriyyo count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/32038156?u=0c68019beb28381ce5205a838937c61e0fe3fee2&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/32038156?u=c26ca9b821fcf6499b84db75f553d4980bf8d023&v=4 url: https://github.com/uriyyo andrew222651: login: andrew222651 @@ -261,7 +266,7 @@ Nimitha-jagadeesha: lucaromagnoli: login: lucaromagnoli count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/38782977?u=e66396859f493b4ddcb3a837a1b2b2039c805417&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/38782977?u=15df02e806a2293af40ac619fba11dbe3c0c4fd4&v=4 url: https://github.com/lucaromagnoli salmantec: login: salmantec @@ -328,11 +333,6 @@ svalouch: count: 2 avatarUrl: https://avatars.githubusercontent.com/u/54674660?v=4 url: https://github.com/svalouch -frankie567: - login: frankie567 - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/1144727?u=f3e79acfe4ed207e15c2145161a8a9759925fcd2&v=4 - url: https://github.com/frankie567 marier-nico: login: marier-nico count: 2 @@ -346,7 +346,7 @@ Dustyposa: aviramha: login: aviramha count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/41201924?u=6883cc4fc13a7b2e60d4deddd4be06f9c5287880&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/41201924?u=ce5d3ea7037c2e6b3f82eff87e2217d4fb63214b&v=4 url: https://github.com/aviramha iwpnd: login: iwpnd diff --git a/docs/en/data/github_sponsors.yml b/docs/en/data/github_sponsors.yml index 7b34719b6..3d8ecdb7a 100644 --- a/docs/en/data/github_sponsors.yml +++ b/docs/en/data/github_sponsors.yml @@ -14,6 +14,9 @@ sponsors: - login: coderabbitai avatarUrl: https://avatars.githubusercontent.com/u/132028505?v=4 url: https://github.com/coderabbitai + - login: greptileai + avatarUrl: https://avatars.githubusercontent.com/u/140149887?v=4 + url: https://github.com/greptileai - login: subtotal avatarUrl: https://avatars.githubusercontent.com/u/176449348?v=4 url: https://github.com/subtotal @@ -41,9 +44,9 @@ sponsors: - login: permitio avatarUrl: https://avatars.githubusercontent.com/u/71775833?v=4 url: https://github.com/permitio -- - login: marvin-robot - avatarUrl: https://avatars.githubusercontent.com/u/41086007?u=b9fcab402d0cd0aec738b6574fe60855cb0cd36d&v=4 - url: https://github.com/marvin-robot +- - login: BoostryJP + avatarUrl: https://avatars.githubusercontent.com/u/57932412?v=4 + url: https://github.com/BoostryJP - login: mercedes-benz avatarUrl: https://avatars.githubusercontent.com/u/34240465?v=4 url: https://github.com/mercedes-benz @@ -53,9 +56,9 @@ sponsors: - login: LambdaTest-Inc avatarUrl: https://avatars.githubusercontent.com/u/171592363?u=96606606a45fa170427206199014f2a5a2a4920b&v=4 url: https://github.com/LambdaTest-Inc - - login: BoostryJP - avatarUrl: https://avatars.githubusercontent.com/u/57932412?v=4 - url: https://github.com/BoostryJP + - login: requestly + avatarUrl: https://avatars.githubusercontent.com/u/12287519?v=4 + url: https://github.com/requestly - login: acsone avatarUrl: https://avatars.githubusercontent.com/u/7601056?v=4 url: https://github.com/acsone @@ -71,27 +74,39 @@ sponsors: - - login: mainframeindustries avatarUrl: https://avatars.githubusercontent.com/u/55092103?v=4 url: https://github.com/mainframeindustries - - login: yasyf - avatarUrl: https://avatars.githubusercontent.com/u/709645?u=f36736b3c6a85f578886ecc42a740e7b436e7a01&v=4 - url: https://github.com/yasyf - - login: alixlahuec avatarUrl: https://avatars.githubusercontent.com/u/29543316?u=44357eb2a93bccf30fb9d389b8befe94a3d00985&v=4 url: https://github.com/alixlahuec + - login: Partho + avatarUrl: https://avatars.githubusercontent.com/u/2034301?u=ce195ac36835cca0cdfe6dd6e897bd38873a1524&v=4 + url: https://github.com/Partho - - login: primer-io avatarUrl: https://avatars.githubusercontent.com/u/62146168?v=4 url: https://github.com/primer-io -- - login: nilslindemann - avatarUrl: https://avatars.githubusercontent.com/u/6892179?u=1dca6a22195d6cd1ab20737c0e19a4c55d639472&v=4 - url: https://github.com/nilslindemann - - login: upciti + - login: xsalagarcia + avatarUrl: https://avatars.githubusercontent.com/u/66035908?v=4 + url: https://github.com/xsalagarcia +- - login: upciti avatarUrl: https://avatars.githubusercontent.com/u/43346262?v=4 url: https://github.com/upciti - - login: thisisfixer - avatarUrl: https://avatars.githubusercontent.com/u/14433035?u=076d52a5b7891c764904af9f462bfb45428e25df&v=4 - url: https://github.com/thisisfixer + - login: GonnaFlyMethod + avatarUrl: https://avatars.githubusercontent.com/u/60840539?u=edf70b373fd4f1a83d3eb7c6802f4b6addb572cf&v=4 + url: https://github.com/GonnaFlyMethod + - login: ChargeStorm + avatarUrl: https://avatars.githubusercontent.com/u/26000165?v=4 + url: https://github.com/ChargeStorm + - login: DanielYang59 + avatarUrl: https://avatars.githubusercontent.com/u/80093591?u=63873f701c7c74aac83c906800a1dddc0bc8c92f&v=4 + url: https://github.com/DanielYang59 + - login: nilslindemann + avatarUrl: https://avatars.githubusercontent.com/u/6892179?u=1dca6a22195d6cd1ab20737c0e19a4c55d639472&v=4 + url: https://github.com/nilslindemann - - login: samuelcolvin avatarUrl: https://avatars.githubusercontent.com/u/4039449?u=42eb3b833047c8c4b4f647a031eaef148c16d93f&v=4 url: https://github.com/samuelcolvin + - login: vincentkoc + avatarUrl: https://avatars.githubusercontent.com/u/25068?u=fbd5b2d51142daa4bdbc21e21953a3b8b8188a4a&v=4 + url: https://github.com/vincentkoc - login: otosky avatarUrl: https://avatars.githubusercontent.com/u/42260747?u=69d089387c743d89427aa4ad8740cfb34045a9e0&v=4 url: https://github.com/otosky @@ -101,6 +116,9 @@ sponsors: - login: roboflow avatarUrl: https://avatars.githubusercontent.com/u/53104118?v=4 url: https://github.com/roboflow + - login: dudikbender + avatarUrl: https://avatars.githubusercontent.com/u/53487583?u=3a57542938ebfd57579a0111db2b297e606d9681&v=4 + url: https://github.com/dudikbender - login: ehaca avatarUrl: https://avatars.githubusercontent.com/u/25950317?u=cec1a3e0643b785288ae8260cc295a85ab344995&v=4 url: https://github.com/ehaca @@ -113,21 +131,15 @@ sponsors: - login: Leay15 avatarUrl: https://avatars.githubusercontent.com/u/32212558?u=c4aa9c1737e515959382a5515381757b1fd86c53&v=4 url: https://github.com/Leay15 - - login: kaoru0310 - avatarUrl: https://avatars.githubusercontent.com/u/80977929?u=1b61d10142b490e56af932ddf08a390fae8ee94f&v=4 - url: https://github.com/kaoru0310 - - login: DelfinaCare - avatarUrl: https://avatars.githubusercontent.com/u/83734439?v=4 - url: https://github.com/DelfinaCare - login: Karine-Bauch avatarUrl: https://avatars.githubusercontent.com/u/90465103?u=7feb1018abb1a5631cfd9a91fea723d1ceb5f49b&v=4 url: https://github.com/Karine-Bauch - login: jugeeem avatarUrl: https://avatars.githubusercontent.com/u/116043716?u=ae590d79c38ac79c91b9c5caa6887d061e865a3d&v=4 url: https://github.com/jugeeem - - login: dudikbender - avatarUrl: https://avatars.githubusercontent.com/u/53487583?u=3a57542938ebfd57579a0111db2b297e606d9681&v=4 - url: https://github.com/dudikbender + - login: connorpark24 + avatarUrl: https://avatars.githubusercontent.com/u/142128990?u=09b84a4beb1f629b77287a837bcf3729785cdd89&v=4 + url: https://github.com/connorpark24 - login: patsatsia avatarUrl: https://avatars.githubusercontent.com/u/61111267?u=3271b85f7a37b479c8d0ae0a235182e83c166edf&v=4 url: https://github.com/patsatsia @@ -140,9 +152,12 @@ sponsors: - login: chickenandstats avatarUrl: https://avatars.githubusercontent.com/u/79477966?u=ae2b894aa954070db1d7830dab99b49eba4e4567&v=4 url: https://github.com/chickenandstats - - login: dodo5522 - avatarUrl: https://avatars.githubusercontent.com/u/1362607?u=9bf1e0e520cccc547c046610c468ce6115bbcf9f&v=4 - url: https://github.com/dodo5522 + - login: kaoru0310 + avatarUrl: https://avatars.githubusercontent.com/u/80977929?u=1b61d10142b490e56af932ddf08a390fae8ee94f&v=4 + url: https://github.com/kaoru0310 + - login: DelfinaCare + avatarUrl: https://avatars.githubusercontent.com/u/83734439?v=4 + url: https://github.com/DelfinaCare - login: knallgelb avatarUrl: https://avatars.githubusercontent.com/u/2358812?u=c48cb6362b309d74cbf144bd6ad3aed3eb443e82&v=4 url: https://github.com/knallgelb @@ -170,9 +185,12 @@ sponsors: - login: Ryandaydev avatarUrl: https://avatars.githubusercontent.com/u/4292423?u=679ff84cb7b988c5795a5fa583857f574a055763&v=4 url: https://github.com/Ryandaydev - - login: vincentkoc - avatarUrl: https://avatars.githubusercontent.com/u/25068?u=fbd5b2d51142daa4bdbc21e21953a3b8b8188a4a&v=4 - url: https://github.com/vincentkoc + - login: jaredtrog + avatarUrl: https://avatars.githubusercontent.com/u/4381365?v=4 + url: https://github.com/jaredtrog + - login: oliverxchen + avatarUrl: https://avatars.githubusercontent.com/u/4471774?u=534191f25e32eeaadda22dfab4b0a428733d5489&v=4 + url: https://github.com/oliverxchen - login: jstanden avatarUrl: https://avatars.githubusercontent.com/u/63288?u=c3658d57d2862c607a0e19c2101c3c51876e36ad&v=4 url: https://github.com/jstanden @@ -197,6 +215,9 @@ sponsors: - login: mintuhouse avatarUrl: https://avatars.githubusercontent.com/u/769950?u=ecfbd79a97d33177e0d093ddb088283cf7fe8444&v=4 url: https://github.com/mintuhouse + - login: dodo5522 + avatarUrl: https://avatars.githubusercontent.com/u/1362607?u=9bf1e0e520cccc547c046610c468ce6115bbcf9f&v=4 + url: https://github.com/dodo5522 - login: wdwinslow avatarUrl: https://avatars.githubusercontent.com/u/11562137?u=371272f2c69e680e0559a7b0a57385e83a5dc728&v=4 url: https://github.com/wdwinslow @@ -212,18 +233,15 @@ sponsors: - login: mjohnsey avatarUrl: https://avatars.githubusercontent.com/u/16784016?u=38fad2e6b411244560b3af99c5f5a4751bc81865&v=4 url: https://github.com/mjohnsey + - login: enguy-hub + avatarUrl: https://avatars.githubusercontent.com/u/16822912?u=2c45f9e7f427b2f2f3b023d7fdb0d44764c92ae8&v=4 + url: https://github.com/enguy-hub - login: ashi-agrawal avatarUrl: https://avatars.githubusercontent.com/u/17105294?u=99c7a854035e5398d8e7b674f2d42baae6c957f8&v=4 url: https://github.com/ashi-agrawal - login: RaamEEIL avatarUrl: https://avatars.githubusercontent.com/u/20320552?v=4 url: https://github.com/RaamEEIL - - login: jaredtrog - avatarUrl: https://avatars.githubusercontent.com/u/4381365?v=4 - url: https://github.com/jaredtrog - - login: oliverxchen - avatarUrl: https://avatars.githubusercontent.com/u/4471774?u=534191f25e32eeaadda22dfab4b0a428733d5489&v=4 - url: https://github.com/oliverxchen - login: ternaus avatarUrl: https://avatars.githubusercontent.com/u/5481618?u=513a26b02a39e7a28d587cd37c6cc877ea368e6e&v=4 url: https://github.com/ternaus @@ -242,7 +260,10 @@ sponsors: - - login: manoelpqueiroz avatarUrl: https://avatars.githubusercontent.com/u/23669137?u=b12e84b28a84369ab5b30bd5a79e5788df5a0756&v=4 url: https://github.com/manoelpqueiroz -- - login: pawamoy +- - login: ceb10n + avatarUrl: https://avatars.githubusercontent.com/u/235213?u=edcce471814a1eba9f0cdaa4cd0de18921a940a6&v=4 + url: https://github.com/ceb10n + - login: pawamoy avatarUrl: https://avatars.githubusercontent.com/u/3999221?u=b030e4c89df2f3a36bc4710b925bdeb6745c9856&v=4 url: https://github.com/pawamoy - login: siavashyj @@ -260,9 +281,9 @@ sponsors: - login: hgalytoby avatarUrl: https://avatars.githubusercontent.com/u/50397689?u=6cc9028f3db63f8f60ad21c17b1ce4b88c4e2e60&v=4 url: https://github.com/hgalytoby - - login: nisutec - avatarUrl: https://avatars.githubusercontent.com/u/25281462?u=e562484c451fdfc59053163f64405f8eb262b8b0&v=4 - url: https://github.com/nisutec + - login: johnl28 + avatarUrl: https://avatars.githubusercontent.com/u/54412955?u=47dd06082d1c39caa90c752eb55566e4f3813957&v=4 + url: https://github.com/johnl28 - login: hoenie-ams avatarUrl: https://avatars.githubusercontent.com/u/25708487?u=cda07434f0509ac728d9edf5e681117c0f6b818b&v=4 url: https://github.com/hoenie-ams @@ -278,33 +299,21 @@ sponsors: - login: petercool avatarUrl: https://avatars.githubusercontent.com/u/37613029?u=75aa8c6729e6e8f85a300561c4dbeef9d65c8797&v=4 url: https://github.com/petercool - - login: JulioPeixoto - avatarUrl: https://avatars.githubusercontent.com/u/96303574?u=27d4614350cae33653f1be35cb47c92a12627ac9&v=4 - url: https://github.com/JulioPeixoto - - login: johnl28 - avatarUrl: https://avatars.githubusercontent.com/u/54412955?u=47dd06082d1c39caa90c752eb55566e4f3813957&v=4 - url: https://github.com/johnl28 - login: PunRabbit avatarUrl: https://avatars.githubusercontent.com/u/70463212?u=1a835cfbc99295a60c8282f6aa6199d1b42241a5&v=4 url: https://github.com/PunRabbit - login: PelicanQ avatarUrl: https://avatars.githubusercontent.com/u/77930606?v=4 url: https://github.com/PelicanQ - - login: miguelgr - avatarUrl: https://avatars.githubusercontent.com/u/1484589?u=54556072b8136efa12ae3b6902032ea2a39ace4b&v=4 - url: https://github.com/miguelgr - - login: WillHogan - avatarUrl: https://avatars.githubusercontent.com/u/1661551?u=8a80356e3e7d5a417157aba7ea565dabc8678327&v=4 - url: https://github.com/WillHogan - login: my3 avatarUrl: https://avatars.githubusercontent.com/u/1825270?v=4 url: https://github.com/my3 - - login: Alisa-lisa - avatarUrl: https://avatars.githubusercontent.com/u/4137964?u=e7e393504f554f4ff15863a1e01a5746863ef9ce&v=4 - url: https://github.com/Alisa-lisa - - login: moonape1226 - avatarUrl: https://avatars.githubusercontent.com/u/8532038?u=d9f8b855a429fff9397c3833c2ff83849ebf989d&v=4 - url: https://github.com/moonape1226 + - login: danielunderwood + avatarUrl: https://avatars.githubusercontent.com/u/4472301?v=4 + url: https://github.com/danielunderwood + - login: rangulvers + avatarUrl: https://avatars.githubusercontent.com/u/5235430?u=e254d4af4ace5a05fa58372ae677c7d26f0d5a53&v=4 + url: https://github.com/rangulvers - login: ddanier avatarUrl: https://avatars.githubusercontent.com/u/113563?u=ed1dc79de72f93bd78581f88ebc6952b62f472da&v=4 url: https://github.com/ddanier @@ -314,24 +323,18 @@ sponsors: - login: slafs avatarUrl: https://avatars.githubusercontent.com/u/210173?v=4 url: https://github.com/slafs - - login: ceb10n - avatarUrl: https://avatars.githubusercontent.com/u/235213?u=edcce471814a1eba9f0cdaa4cd0de18921a940a6&v=4 - url: https://github.com/ceb10n - login: tochikuji avatarUrl: https://avatars.githubusercontent.com/u/851759?v=4 url: https://github.com/tochikuji - - login: xncbf - avatarUrl: https://avatars.githubusercontent.com/u/9462045?u=a80a7bb349555b277645632ed66639ff43400614&v=4 - url: https://github.com/xncbf - - login: DMantis - avatarUrl: https://avatars.githubusercontent.com/u/9536869?u=652dd0d49717803c0cbcbf44f7740e53cf2d4892&v=4 - url: https://github.com/DMantis + - login: miguelgr + avatarUrl: https://avatars.githubusercontent.com/u/1484589?u=54556072b8136efa12ae3b6902032ea2a39ace4b&v=4 + url: https://github.com/miguelgr + - login: WillHogan + avatarUrl: https://avatars.githubusercontent.com/u/1661551?u=8a80356e3e7d5a417157aba7ea565dabc8678327&v=4 + url: https://github.com/WillHogan - login: hard-coders avatarUrl: https://avatars.githubusercontent.com/u/9651103?u=95db33927bbff1ed1c07efddeb97ac2ff33068ed&v=4 url: https://github.com/hard-coders - - login: supdann - avatarUrl: https://avatars.githubusercontent.com/u/9986994?u=9671810f4ae9504c063227fee34fd47567ff6954&v=4 - url: https://github.com/supdann - login: mntolia avatarUrl: https://avatars.githubusercontent.com/u/10390224?v=4 url: https://github.com/mntolia @@ -344,12 +347,9 @@ sponsors: - login: joshuatz avatarUrl: https://avatars.githubusercontent.com/u/17817563?u=f1bf05b690d1fc164218f0b420cdd3acb7913e21&v=4 url: https://github.com/joshuatz - - login: danielunderwood - avatarUrl: https://avatars.githubusercontent.com/u/4472301?v=4 - url: https://github.com/danielunderwood - - login: rangulvers - avatarUrl: https://avatars.githubusercontent.com/u/5235430?u=e254d4af4ace5a05fa58372ae677c7d26f0d5a53&v=4 - url: https://github.com/rangulvers + - login: nisutec + avatarUrl: https://avatars.githubusercontent.com/u/25281462?u=e562484c451fdfc59053163f64405f8eb262b8b0&v=4 + url: https://github.com/nisutec - login: sdevkota avatarUrl: https://avatars.githubusercontent.com/u/5250987?u=4ed9a120c89805a8aefda1cbdc0cf6512e64d1b4&v=4 url: https://github.com/sdevkota @@ -365,39 +365,45 @@ sponsors: - login: harsh183 avatarUrl: https://avatars.githubusercontent.com/u/7780198?v=4 url: https://github.com/harsh183 -- - login: KOZ39 - avatarUrl: https://avatars.githubusercontent.com/u/38822500?u=9dfc0a697df1c9628f08e20dc3fb17b1afc4e5a7&v=4 - url: https://github.com/KOZ39 - - login: rwxd - avatarUrl: https://avatars.githubusercontent.com/u/40308458?u=cd04a39e3655923be4f25c2ba8a5a07b3da3230a&v=4 - url: https://github.com/rwxd - - login: morzan1001 + - login: moonape1226 + avatarUrl: https://avatars.githubusercontent.com/u/8532038?u=d9f8b855a429fff9397c3833c2ff83849ebf989d&v=4 + url: https://github.com/moonape1226 + - login: xncbf + avatarUrl: https://avatars.githubusercontent.com/u/9462045?u=a80a7bb349555b277645632ed66639ff43400614&v=4 + url: https://github.com/xncbf + - login: DMantis + avatarUrl: https://avatars.githubusercontent.com/u/9536869?u=652dd0d49717803c0cbcbf44f7740e53cf2d4892&v=4 + url: https://github.com/DMantis +- - login: morzan1001 avatarUrl: https://avatars.githubusercontent.com/u/47593005?u=c30ab7230f82a12a9b938dcb54f84a996931409a&v=4 url: https://github.com/morzan1001 - - login: azharthegeek - avatarUrl: https://avatars.githubusercontent.com/u/51288109?u=0987b2a9f39c21ccb071b6bdce0fc60d8492f8e8&v=4 - url: https://github.com/azharthegeek - - login: Olegt0rr - avatarUrl: https://avatars.githubusercontent.com/u/25399456?u=3e87b5239a2f4600975ba13be73054f8567c6060&v=4 - url: https://github.com/Olegt0rr - login: larsyngvelundin avatarUrl: https://avatars.githubusercontent.com/u/34173819?u=74958599695bf83ac9f1addd935a51548a10c6b0&v=4 url: https://github.com/larsyngvelundin - login: andrecorumba avatarUrl: https://avatars.githubusercontent.com/u/37807517?u=9b9be3b41da9bda60957da9ef37b50dbf65baa61&v=4 url: https://github.com/andrecorumba - - login: ChenPu2002 - avatarUrl: https://avatars.githubusercontent.com/u/113831763?v=4 - url: https://github.com/ChenPu2002 + - login: KOZ39 + avatarUrl: https://avatars.githubusercontent.com/u/38822500?u=9dfc0a697df1c9628f08e20dc3fb17b1afc4e5a7&v=4 + url: https://github.com/KOZ39 + - login: rwxd + avatarUrl: https://avatars.githubusercontent.com/u/40308458?u=cd04a39e3655923be4f25c2ba8a5a07b3da3230a&v=4 + url: https://github.com/rwxd + - login: hippoley + avatarUrl: https://avatars.githubusercontent.com/u/135493401?u=1164ef48a645a7c12664fabc1638fbb7e1c459b0&v=4 + url: https://github.com/hippoley - login: CoderDeltaLAN avatarUrl: https://avatars.githubusercontent.com/u/152043745?u=4ff541efffb7d134e60c5fcf2dd1e343f90bb782&v=4 url: https://github.com/CoderDeltaLAN - - login: aghents - avatarUrl: https://avatars.githubusercontent.com/u/60949885?u=d8616ddf22cf998a712cdceefd6a0256a178fe9d&v=4 - url: https://github.com/aghents - - login: 0ne-stone + - login: chris1ding1 + avatarUrl: https://avatars.githubusercontent.com/u/194386334?u=5500604b50e35ed8a5aeb82ce34aa5d3ee3f88c7&v=4 + url: https://github.com/chris1ding1 + - login: onestn avatarUrl: https://avatars.githubusercontent.com/u/62360849?u=746dd21c34e7e06eefb11b03e8bb01aaae3c2a4f&v=4 - url: https://github.com/0ne-stone + url: https://github.com/onestn + - login: Rubinskiy + avatarUrl: https://avatars.githubusercontent.com/u/62457878?u=f2e35ed3d196a99cfadb5a29a91950342af07e34&v=4 + url: https://github.com/Rubinskiy - login: nayasinghania avatarUrl: https://avatars.githubusercontent.com/u/74111380?u=752e99a5e139389fdc0a0677122adc08438eb076&v=4 url: https://github.com/nayasinghania @@ -407,6 +413,9 @@ sponsors: - login: andreagrandi avatarUrl: https://avatars.githubusercontent.com/u/636391?u=13d90cb8ec313593a5b71fbd4e33b78d6da736f5&v=4 url: https://github.com/andreagrandi + - login: Olegt0rr + avatarUrl: https://avatars.githubusercontent.com/u/25399456?u=3e87b5239a2f4600975ba13be73054f8567c6060&v=4 + url: https://github.com/Olegt0rr - login: msserpa avatarUrl: https://avatars.githubusercontent.com/u/6334934?u=82c4489eb1559d88d2990d60001901b14f722bbb&v=4 url: https://github.com/msserpa diff --git a/docs/en/data/sponsors.yml b/docs/en/data/sponsors.yml index ae28410e7..943b92adb 100644 --- a/docs/en/data/sponsors.yml +++ b/docs/en/data/sponsors.yml @@ -26,6 +26,9 @@ gold: - url: https://docs.railway.com/guides/fastapi?utm_medium=integration&utm_source=docs&utm_campaign=fastapi title: Deploy enterprise applications at startup speed img: https://fastapi.tiangolo.com/img/sponsors/railway.png + - url: https://serpapi.com/?utm_source=fastapi_website + title: "SerpApi: Web Search API" + img: https://fastapi.tiangolo.com/img/sponsors/serpapi.png silver: - url: https://databento.com/?utm_source=fastapi&utm_medium=sponsor&utm_content=display title: Pay as you go for market data @@ -58,3 +61,6 @@ bronze: - url: https://lambdatest.com/?utm_source=fastapi&utm_medium=partner&utm_campaign=sponsor&utm_term=opensource&utm_content=webpage title: LambdaTest, AI-Powered Cloud-based Test Orchestration Platform img: https://fastapi.tiangolo.com/img/sponsors/lambdatest.png + - url: https://requestly.com/fastapi + title: All-in-one platform to Test, Mock and Intercept APIs. Built for speed, privacy and offline support. + img: https://fastapi.tiangolo.com/img/sponsors/requestly.png diff --git a/docs/en/data/sponsors_badge.yml b/docs/en/data/sponsors_badge.yml index 62ba6a84c..14f55805c 100644 --- a/docs/en/data/sponsors_badge.yml +++ b/docs/en/data/sponsors_badge.yml @@ -46,3 +46,4 @@ logins: - madisonredtfeldt - railwayapp - subtotal + - requestly diff --git a/docs/en/data/topic_repos.yml b/docs/en/data/topic_repos.yml index 9d95fb8b1..1bb6fd70d 100644 --- a/docs/en/data/topic_repos.yml +++ b/docs/en/data/topic_repos.yml @@ -1,81 +1,86 @@ - name: full-stack-fastapi-template html_url: https://github.com/fastapi/full-stack-fastapi-template - stars: 38085 + stars: 38779 owner_login: fastapi owner_html_url: https://github.com/fastapi - name: Hello-Python html_url: https://github.com/mouredev/Hello-Python - stars: 32243 + stars: 32726 owner_login: mouredev owner_html_url: https://github.com/mouredev - name: serve html_url: https://github.com/jina-ai/serve - stars: 21754 + stars: 21779 owner_login: jina-ai owner_html_url: https://github.com/jina-ai - name: HivisionIDPhotos html_url: https://github.com/Zeyi-Lin/HivisionIDPhotos - stars: 19400 + stars: 20028 owner_login: Zeyi-Lin owner_html_url: https://github.com/Zeyi-Lin - name: sqlmodel html_url: https://github.com/fastapi/sqlmodel - stars: 16859 + stars: 17038 owner_login: fastapi owner_html_url: https://github.com/fastapi - name: Douyin_TikTok_Download_API html_url: https://github.com/Evil0ctal/Douyin_TikTok_Download_API - stars: 14452 + stars: 14786 owner_login: Evil0ctal owner_html_url: https://github.com/Evil0ctal - name: fastapi-best-practices html_url: https://github.com/zhanymkanov/fastapi-best-practices - stars: 13613 + stars: 13968 owner_login: zhanymkanov owner_html_url: https://github.com/zhanymkanov +- name: machine-learning-zoomcamp + html_url: https://github.com/DataTalksClub/machine-learning-zoomcamp + stars: 12171 + owner_login: DataTalksClub + owner_html_url: https://github.com/DataTalksClub - name: fastapi_mcp html_url: https://github.com/tadata-org/fastapi_mcp - stars: 10624 + stars: 10976 owner_login: tadata-org owner_html_url: https://github.com/tadata-org - name: awesome-fastapi html_url: https://github.com/mjhea0/awesome-fastapi - stars: 10415 + stars: 10618 owner_login: mjhea0 owner_html_url: https://github.com/mjhea0 -- name: FastUI - html_url: https://github.com/pydantic/FastUI - stars: 8879 - owner_login: pydantic - owner_html_url: https://github.com/pydantic -- name: XHS-Downloader - html_url: https://github.com/JoeanAmier/XHS-Downloader - stars: 8824 - owner_login: JoeanAmier - owner_html_url: https://github.com/JoeanAmier - name: SurfSense html_url: https://github.com/MODSetter/SurfSense - stars: 8257 + stars: 10243 owner_login: MODSetter owner_html_url: https://github.com/MODSetter -- name: FileCodeBox - html_url: https://github.com/vastsa/FileCodeBox - stars: 7367 - owner_login: vastsa - owner_html_url: https://github.com/vastsa +- name: XHS-Downloader + html_url: https://github.com/JoeanAmier/XHS-Downloader + stars: 9062 + owner_login: JoeanAmier + owner_html_url: https://github.com/JoeanAmier +- name: FastUI + html_url: https://github.com/pydantic/FastUI + stars: 8892 + owner_login: pydantic + owner_html_url: https://github.com/pydantic - name: polar html_url: https://github.com/polarsource/polar - stars: 7291 + stars: 8084 owner_login: polarsource owner_html_url: https://github.com/polarsource +- name: FileCodeBox + html_url: https://github.com/vastsa/FileCodeBox + stars: 7494 + owner_login: vastsa + owner_html_url: https://github.com/vastsa - name: nonebot2 html_url: https://github.com/nonebot/nonebot2 - stars: 7065 + stars: 7128 owner_login: nonebot owner_html_url: https://github.com/nonebot - name: hatchet html_url: https://github.com/hatchet-dev/hatchet - stars: 6070 + stars: 6155 owner_login: hatchet-dev owner_html_url: https://github.com/hatchet-dev - name: serge @@ -85,27 +90,27 @@ owner_html_url: https://github.com/serge-chat - name: fastapi-users html_url: https://github.com/fastapi-users/fastapi-users - stars: 5599 + stars: 5683 owner_login: fastapi-users owner_html_url: https://github.com/fastapi-users - name: strawberry html_url: https://github.com/strawberry-graphql/strawberry - stars: 4422 + stars: 4452 owner_login: strawberry-graphql owner_html_url: https://github.com/strawberry-graphql - name: chatgpt-web-share html_url: https://github.com/chatpire/chatgpt-web-share - stars: 4301 + stars: 4296 owner_login: chatpire owner_html_url: https://github.com/chatpire - name: poem html_url: https://github.com/poem-web/poem - stars: 4197 + stars: 4235 owner_login: poem-web owner_html_url: https://github.com/poem-web - name: dynaconf html_url: https://github.com/dynaconf/dynaconf - stars: 4144 + stars: 4174 owner_login: dynaconf owner_html_url: https://github.com/dynaconf - name: atrilabs-engine @@ -115,42 +120,42 @@ owner_html_url: https://github.com/Atri-Labs - name: Kokoro-FastAPI html_url: https://github.com/remsky/Kokoro-FastAPI - stars: 3739 + stars: 3875 owner_login: remsky owner_html_url: https://github.com/remsky - name: logfire html_url: https://github.com/pydantic/logfire - stars: 3614 + stars: 3717 owner_login: pydantic owner_html_url: https://github.com/pydantic - name: LitServe html_url: https://github.com/Lightning-AI/LitServe - stars: 3578 + stars: 3615 owner_login: Lightning-AI owner_html_url: https://github.com/Lightning-AI - name: datamodel-code-generator html_url: https://github.com/koxudaxi/datamodel-code-generator - stars: 3496 + stars: 3554 owner_login: koxudaxi owner_html_url: https://github.com/koxudaxi -- name: farfalle - html_url: https://github.com/rashadphz/farfalle - stars: 3459 - owner_login: rashadphz - owner_html_url: https://github.com/rashadphz -- name: fastapi-admin - html_url: https://github.com/fastapi-admin/fastapi-admin - stars: 3456 - owner_login: fastapi-admin - owner_html_url: https://github.com/fastapi-admin - name: huma html_url: https://github.com/danielgtaylor/huma - stars: 3447 + stars: 3521 owner_login: danielgtaylor owner_html_url: https://github.com/danielgtaylor +- name: fastapi-admin + html_url: https://github.com/fastapi-admin/fastapi-admin + stars: 3497 + owner_login: fastapi-admin + owner_html_url: https://github.com/fastapi-admin +- name: farfalle + html_url: https://github.com/rashadphz/farfalle + stars: 3476 + owner_login: rashadphz + owner_html_url: https://github.com/rashadphz - name: tracecat html_url: https://github.com/TracecatHQ/tracecat - stars: 3254 + stars: 3310 owner_login: TracecatHQ owner_html_url: https://github.com/TracecatHQ - name: opyrator @@ -160,336 +165,331 @@ owner_html_url: https://github.com/ml-tooling - name: docarray html_url: https://github.com/docarray/docarray - stars: 3107 + stars: 3108 owner_login: docarray owner_html_url: https://github.com/docarray - name: fastapi-realworld-example-app html_url: https://github.com/nsidnev/fastapi-realworld-example-app - stars: 2936 + stars: 2945 owner_login: nsidnev owner_html_url: https://github.com/nsidnev - name: uvicorn-gunicorn-fastapi-docker html_url: https://github.com/tiangolo/uvicorn-gunicorn-fastapi-docker - stars: 2804 + stars: 2809 owner_login: tiangolo owner_html_url: https://github.com/tiangolo -- name: best-of-web-python - html_url: https://github.com/ml-tooling/best-of-web-python - stars: 2610 - owner_login: ml-tooling - owner_html_url: https://github.com/ml-tooling +- name: devpush + html_url: https://github.com/hunvreus/devpush + stars: 2784 + owner_login: hunvreus + owner_html_url: https://github.com/hunvreus - name: mcp-context-forge html_url: https://github.com/IBM/mcp-context-forge - stars: 2572 + stars: 2763 owner_login: IBM owner_html_url: https://github.com/IBM +- name: best-of-web-python + html_url: https://github.com/ml-tooling/best-of-web-python + stars: 2630 + owner_login: ml-tooling + owner_html_url: https://github.com/ml-tooling - name: fastapi-react html_url: https://github.com/Buuntu/fastapi-react - stars: 2451 + stars: 2464 owner_login: Buuntu owner_html_url: https://github.com/Buuntu -- name: RasaGPT - html_url: https://github.com/paulpierre/RasaGPT - stars: 2441 - owner_login: paulpierre - owner_html_url: https://github.com/paulpierre - name: FastAPI-template html_url: https://github.com/s3rius/FastAPI-template - stars: 2424 + stars: 2453 owner_login: s3rius owner_html_url: https://github.com/s3rius +- name: RasaGPT + html_url: https://github.com/paulpierre/RasaGPT + stars: 2444 + owner_login: paulpierre + owner_html_url: https://github.com/paulpierre - name: sqladmin html_url: https://github.com/aminalaee/sqladmin - stars: 2357 + stars: 2423 owner_login: aminalaee owner_html_url: https://github.com/aminalaee - name: nextpy html_url: https://github.com/dot-agent/nextpy - stars: 2324 + stars: 2325 owner_login: dot-agent owner_html_url: https://github.com/dot-agent - name: supabase-py html_url: https://github.com/supabase/supabase-py - stars: 2236 + stars: 2292 owner_login: supabase owner_html_url: https://github.com/supabase - name: 30-Days-of-Python html_url: https://github.com/codingforentrepreneurs/30-Days-of-Python - stars: 2210 + stars: 2214 owner_login: codingforentrepreneurs owner_html_url: https://github.com/codingforentrepreneurs +- name: Yuxi-Know + html_url: https://github.com/xerrors/Yuxi-Know + stars: 2212 + owner_login: xerrors + owner_html_url: https://github.com/xerrors - name: langserve html_url: https://github.com/langchain-ai/langserve - stars: 2171 + stars: 2191 owner_login: langchain-ai owner_html_url: https://github.com/langchain-ai - name: fastapi-utils html_url: https://github.com/fastapiutils/fastapi-utils - stars: 2164 + stars: 2185 owner_login: fastapiutils owner_html_url: https://github.com/fastapiutils - name: solara html_url: https://github.com/widgetti/solara - stars: 2102 + stars: 2111 owner_login: widgetti owner_html_url: https://github.com/widgetti -- name: Yuxi-Know - html_url: https://github.com/xerrors/Yuxi-Know - stars: 1995 - owner_login: xerrors - owner_html_url: https://github.com/xerrors - name: mangum html_url: https://github.com/Kludex/mangum - stars: 1989 + stars: 2011 owner_login: Kludex owner_html_url: https://github.com/Kludex -- name: python-week-2022 - html_url: https://github.com/rochacbruno/python-week-2022 - stars: 1816 - owner_login: rochacbruno - owner_html_url: https://github.com/rochacbruno - name: agentkit html_url: https://github.com/BCG-X-Official/agentkit - stars: 1789 + stars: 1826 owner_login: BCG-X-Official owner_html_url: https://github.com/BCG-X-Official +- name: python-week-2022 + html_url: https://github.com/rochacbruno/python-week-2022 + stars: 1815 + owner_login: rochacbruno + owner_html_url: https://github.com/rochacbruno - name: manage-fastapi html_url: https://github.com/ycd/manage-fastapi - stars: 1780 + stars: 1787 owner_login: ycd owner_html_url: https://github.com/ycd - name: ormar html_url: https://github.com/collerek/ormar - stars: 1777 + stars: 1780 owner_login: collerek owner_html_url: https://github.com/collerek +- name: vue-fastapi-admin + html_url: https://github.com/mizhexiaoxiao/vue-fastapi-admin + stars: 1758 + owner_login: mizhexiaoxiao + owner_html_url: https://github.com/mizhexiaoxiao - name: openapi-python-client html_url: https://github.com/openapi-generators/openapi-python-client - stars: 1707 + stars: 1731 owner_login: openapi-generators owner_html_url: https://github.com/openapi-generators - name: piccolo html_url: https://github.com/piccolo-orm/piccolo - stars: 1695 + stars: 1711 owner_login: piccolo-orm owner_html_url: https://github.com/piccolo-orm -- name: vue-fastapi-admin - html_url: https://github.com/mizhexiaoxiao/vue-fastapi-admin - stars: 1695 - owner_login: mizhexiaoxiao - owner_html_url: https://github.com/mizhexiaoxiao - name: fastapi-cache html_url: https://github.com/long2ice/fastapi-cache - stars: 1653 + stars: 1677 owner_login: long2ice owner_html_url: https://github.com/long2ice +- name: slowapi + html_url: https://github.com/laurentS/slowapi + stars: 1669 + owner_login: laurentS + owner_html_url: https://github.com/laurentS - name: langchain-serve html_url: https://github.com/jina-ai/langchain-serve - stars: 1635 + stars: 1632 owner_login: jina-ai owner_html_url: https://github.com/jina-ai - name: termpair html_url: https://github.com/cs01/termpair - stars: 1624 + stars: 1621 owner_login: cs01 owner_html_url: https://github.com/cs01 -- name: slowapi - html_url: https://github.com/laurentS/slowapi - stars: 1620 - owner_login: laurentS - owner_html_url: https://github.com/laurentS +- name: FastAPI-boilerplate + html_url: https://github.com/benavlabs/FastAPI-boilerplate + stars: 1596 + owner_login: benavlabs + owner_html_url: https://github.com/benavlabs - name: coronavirus-tracker-api html_url: https://github.com/ExpDev07/coronavirus-tracker-api - stars: 1576 + stars: 1573 owner_login: ExpDev07 owner_html_url: https://github.com/ExpDev07 - name: fastapi-crudrouter html_url: https://github.com/awtkns/fastapi-crudrouter - stars: 1546 + stars: 1553 owner_login: awtkns owner_html_url: https://github.com/awtkns -- name: FastAPI-boilerplate - html_url: https://github.com/benavlabs/FastAPI-boilerplate - stars: 1516 - owner_login: benavlabs - owner_html_url: https://github.com/benavlabs - name: awesome-fastapi-projects html_url: https://github.com/Kludex/awesome-fastapi-projects - stars: 1481 + stars: 1485 owner_login: Kludex owner_html_url: https://github.com/Kludex - name: fastapi-pagination html_url: https://github.com/uriyyo/fastapi-pagination - stars: 1453 + stars: 1473 owner_login: uriyyo owner_html_url: https://github.com/uriyyo - name: bracket html_url: https://github.com/evroon/bracket - stars: 1415 + stars: 1470 owner_login: evroon owner_html_url: https://github.com/evroon -- name: awesome-python-resources - html_url: https://github.com/DjangoEx/awesome-python-resources - stars: 1413 - owner_login: DjangoEx - owner_html_url: https://github.com/DjangoEx +- name: fastapi-langgraph-agent-production-ready-template + html_url: https://github.com/wassim249/fastapi-langgraph-agent-production-ready-template + stars: 1456 + owner_login: wassim249 + owner_html_url: https://github.com/wassim249 - name: fastapi-boilerplate html_url: https://github.com/teamhide/fastapi-boilerplate - stars: 1406 + stars: 1424 owner_login: teamhide owner_html_url: https://github.com/teamhide -- name: budgetml - html_url: https://github.com/ebhy/budgetml - stars: 1346 - owner_login: ebhy - owner_html_url: https://github.com/ebhy +- name: awesome-python-resources + html_url: https://github.com/DjangoEx/awesome-python-resources + stars: 1420 + owner_login: DjangoEx + owner_html_url: https://github.com/DjangoEx - name: fastapi-amis-admin html_url: https://github.com/amisadmin/fastapi-amis-admin - stars: 1342 + stars: 1363 owner_login: amisadmin owner_html_url: https://github.com/amisadmin -- name: fastapi-langgraph-agent-production-ready-template - html_url: https://github.com/wassim249/fastapi-langgraph-agent-production-ready-template - stars: 1334 - owner_login: wassim249 - owner_html_url: https://github.com/wassim249 +- name: fastcrud + html_url: https://github.com/benavlabs/fastcrud + stars: 1362 + owner_login: benavlabs + owner_html_url: https://github.com/benavlabs +- name: budgetml + html_url: https://github.com/ebhy/budgetml + stars: 1345 + owner_login: ebhy + owner_html_url: https://github.com/ebhy - name: fastapi-tutorial html_url: https://github.com/liaogx/fastapi-tutorial - stars: 1303 + stars: 1315 owner_login: liaogx owner_html_url: https://github.com/liaogx - name: fastapi_best_architecture html_url: https://github.com/fastapi-practices/fastapi_best_architecture - stars: 1276 + stars: 1311 owner_login: fastapi-practices owner_html_url: https://github.com/fastapi-practices -- name: fastcrud - html_url: https://github.com/benavlabs/fastcrud - stars: 1272 - owner_login: benavlabs - owner_html_url: https://github.com/benavlabs - name: fastapi-code-generator html_url: https://github.com/koxudaxi/fastapi-code-generator - stars: 1253 + stars: 1270 owner_login: koxudaxi owner_html_url: https://github.com/koxudaxi - name: prometheus-fastapi-instrumentator html_url: https://github.com/trallnag/prometheus-fastapi-instrumentator - stars: 1246 + stars: 1264 owner_login: trallnag owner_html_url: https://github.com/trallnag -- name: bolt-python - html_url: https://github.com/slackapi/bolt-python - stars: 1221 - owner_login: slackapi - owner_html_url: https://github.com/slackapi - name: bedrock-chat html_url: https://github.com/aws-samples/bedrock-chat - stars: 1220 + stars: 1243 owner_login: aws-samples owner_html_url: https://github.com/aws-samples +- name: bolt-python + html_url: https://github.com/slackapi/bolt-python + stars: 1238 + owner_login: slackapi + owner_html_url: https://github.com/slackapi - name: fastapi_production_template html_url: https://github.com/zhanymkanov/fastapi_production_template - stars: 1202 + stars: 1209 owner_login: zhanymkanov owner_html_url: https://github.com/zhanymkanov - name: fastapi-scaff html_url: https://github.com/atpuxiner/fastapi-scaff - stars: 1193 + stars: 1200 owner_login: atpuxiner owner_html_url: https://github.com/atpuxiner - name: langchain-extract html_url: https://github.com/langchain-ai/langchain-extract - stars: 1164 + stars: 1173 owner_login: langchain-ai owner_html_url: https://github.com/langchain-ai - name: fastapi-alembic-sqlmodel-async html_url: https://github.com/jonra1993/fastapi-alembic-sqlmodel-async - stars: 1149 + stars: 1162 owner_login: jonra1993 owner_html_url: https://github.com/jonra1993 - name: odmantic html_url: https://github.com/art049/odmantic - stars: 1133 + stars: 1137 owner_login: art049 owner_html_url: https://github.com/art049 - name: restish html_url: https://github.com/rest-sh/restish - stars: 1122 + stars: 1129 owner_login: rest-sh owner_html_url: https://github.com/rest-sh -- name: runhouse - html_url: https://github.com/run-house/runhouse - stars: 1047 +- name: kubetorch + html_url: https://github.com/run-house/kubetorch + stars: 1065 owner_login: run-house owner_html_url: https://github.com/run-house - name: flock html_url: https://github.com/Onelevenvy/flock - stars: 1027 + stars: 1039 owner_login: Onelevenvy owner_html_url: https://github.com/Onelevenvy - name: authx html_url: https://github.com/yezz123/authx - stars: 999 + stars: 1017 owner_login: yezz123 owner_html_url: https://github.com/yezz123 - name: autollm html_url: https://github.com/viddexa/autollm - stars: 999 + stars: 997 owner_login: viddexa owner_html_url: https://github.com/viddexa - name: lanarky html_url: https://github.com/ajndkr/lanarky - stars: 995 + stars: 993 owner_login: ajndkr owner_html_url: https://github.com/ajndkr -- name: titiler - html_url: https://github.com/developmentseed/titiler - stars: 952 - owner_login: developmentseed - owner_html_url: https://github.com/developmentseed -- name: energy-forecasting - html_url: https://github.com/iusztinpaul/energy-forecasting - stars: 946 - owner_login: iusztinpaul - owner_html_url: https://github.com/iusztinpaul -- name: secure - html_url: https://github.com/TypeError/secure - stars: 944 - owner_login: TypeError - owner_html_url: https://github.com/TypeError -- name: langcorn - html_url: https://github.com/msoedov/langcorn - stars: 934 - owner_login: msoedov - owner_html_url: https://github.com/msoedov - name: RuoYi-Vue3-FastAPI html_url: https://github.com/insistence/RuoYi-Vue3-FastAPI - stars: 930 + stars: 974 owner_login: insistence owner_html_url: https://github.com/insistence - name: aktools html_url: https://github.com/akfamily/aktools - stars: 916 + stars: 972 owner_login: akfamily owner_html_url: https://github.com/akfamily +- name: titiler + html_url: https://github.com/developmentseed/titiler + stars: 965 + owner_login: developmentseed + owner_html_url: https://github.com/developmentseed +- name: secure + html_url: https://github.com/TypeError/secure + stars: 953 + owner_login: TypeError + owner_html_url: https://github.com/TypeError +- name: energy-forecasting + html_url: https://github.com/iusztinpaul/energy-forecasting + stars: 949 + owner_login: iusztinpaul + owner_html_url: https://github.com/iusztinpaul - name: every-pdf html_url: https://github.com/DDULDDUCK/every-pdf - stars: 907 + stars: 942 owner_login: DDULDDUCK owner_html_url: https://github.com/DDULDDUCK -- name: marker-api - html_url: https://github.com/adithya-s-k/marker-api - stars: 903 - owner_login: adithya-s-k - owner_html_url: https://github.com/adithya-s-k +- name: langcorn + html_url: https://github.com/msoedov/langcorn + stars: 933 + owner_login: msoedov + owner_html_url: https://github.com/msoedov - name: fastapi-observability html_url: https://github.com/blueswen/fastapi-observability - stars: 902 + stars: 923 owner_login: blueswen owner_html_url: https://github.com/blueswen -- name: fastapi-do-zero - html_url: https://github.com/dunossauro/fastapi-do-zero - stars: 900 - owner_login: dunossauro - owner_html_url: https://github.com/dunossauro diff --git a/docs/en/data/translation_reviewers.yml b/docs/en/data/translation_reviewers.yml index 68ef01f6d..45aa55e5e 100644 --- a/docs/en/data/translation_reviewers.yml +++ b/docs/en/data/translation_reviewers.yml @@ -776,7 +776,7 @@ pablocm83: d2a-raudenaerde: login: d2a-raudenaerde count: 7 - avatarUrl: https://avatars.githubusercontent.com/u/5213150?v=4 + avatarUrl: https://avatars.githubusercontent.com/u/5213150?u=e6d0ef65c571c7e544fc1c7ec151c7c0a72fb6bb&v=4 url: https://github.com/d2a-raudenaerde valentinDruzhinin: login: valentinDruzhinin @@ -1206,7 +1206,7 @@ akagaeng: phamquanganh31101998: login: phamquanganh31101998 count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/43257497?u=36fa4ee689415d869a98453083a7c4213d2136ee&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/43257497?u=6b3419ea9e318c356c42a973fb947682590bd8d3&v=4 url: https://github.com/phamquanganh31101998 peebbv6364: login: peebbv6364 @@ -1806,7 +1806,7 @@ MrL8199: ivintoiu: login: ivintoiu count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/1853336?u=5e3d0977f44661fb9712fa297cc8f7608ea6ce48&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/1853336?u=b537c905ad08b69993de8796fb235c8d4d47f039&v=4 url: https://github.com/ivintoiu TechnoService2: login: TechnoService2 @@ -1841,7 +1841,7 @@ NavesSapnis: eqsdxr: login: eqsdxr count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/157279130?u=58fddf77ed76966eaa8c73eea9bea4bb0c53b673&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/157279130?u=d7aaffb29f542b647cf0f6b0e05722490863658a&v=4 url: https://github.com/eqsdxr syedasamina56: login: syedasamina56 diff --git a/docs/en/data/translators.yml b/docs/en/data/translators.yml index cf61eee8e..a4b87e1bf 100644 --- a/docs/en/data/translators.yml +++ b/docs/en/data/translators.yml @@ -1,6 +1,6 @@ nilslindemann: login: nilslindemann - count: 122 + count: 124 avatarUrl: https://avatars.githubusercontent.com/u/6892179?u=1dca6a22195d6cd1ab20737c0e19a4c55d639472&v=4 url: https://github.com/nilslindemann jaystone776: @@ -103,6 +103,11 @@ pablocm83: count: 8 avatarUrl: https://avatars.githubusercontent.com/u/28315068?u=3310fbb05bb8bfc50d2c48b6cb64ac9ee4a14549&v=4 url: https://github.com/pablocm83 +tiangolo: + login: tiangolo + count: 7 + avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4 + url: https://github.com/tiangolo ptt3199: login: ptt3199 count: 7 @@ -118,11 +123,6 @@ batlopes: count: 6 avatarUrl: https://avatars.githubusercontent.com/u/33462923?u=0fb3d7acb316764616f11e4947faf080e49ad8d9&v=4 url: https://github.com/batlopes -tiangolo: - login: tiangolo - count: 6 - avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4 - url: https://github.com/tiangolo lucasbalieiro: login: lucasbalieiro count: 6 diff --git a/docs/en/docs/advanced/advanced-dependencies.md b/docs/en/docs/advanced/advanced-dependencies.md index e0404b389..5d6a40f46 100644 --- a/docs/en/docs/advanced/advanced-dependencies.md +++ b/docs/en/docs/advanced/advanced-dependencies.md @@ -70,12 +70,22 @@ If you understood all this, you already know how those utility tools for securit You most probably don't need these technical details. -These details are useful mainly if you had a FastAPI application older than 0.118.0 and you are facing issues with dependencies with `yield`. +These details are useful mainly if you had a FastAPI application older than 0.121.0 and you are facing issues with dependencies with `yield`. /// Dependencies with `yield` have evolved over time to account for the different use cases and to fix some issues, here's a summary of what has changed. +### Dependencies with `yield` and `scope` { #dependencies-with-yield-and-scope } + +In version 0.121.0, FastAPI added support for `Depends(scope="function")` for dependencies with `yield`. + +Using `Depends(scope="function")`, the exit code after `yield` is executed right after the *path operation function* is finished, before the response is sent back to the client. + +And when using `Depends(scope="request")` (the default), the exit code after `yield` is executed after the response is sent. + +You can read more about it in the docs for [Dependencies with `yield` - Early exit and `scope`](../tutorial/dependencies/dependencies-with-yield.md#early-exit-and-scope). + ### Dependencies with `yield` and `StreamingResponse`, Technical Details { #dependencies-with-yield-and-streamingresponse-technical-details } Before FastAPI 0.118.0, if you used a dependency with `yield`, it would run the exit code after the *path operation function* returned but right before sending the response. diff --git a/docs/en/docs/advanced/events.md b/docs/en/docs/advanced/events.md index c805e81ee..d9e3cb52e 100644 --- a/docs/en/docs/advanced/events.md +++ b/docs/en/docs/advanced/events.md @@ -154,7 +154,7 @@ Underneath, in the ASGI technical specification, this is part of the Starlette's Lifespan' docs. +You can read more about the Starlette `lifespan` handlers in Starlette's Lifespan' docs. Including how to handle lifespan state that can be used in other areas of your code. diff --git a/docs/en/docs/advanced/middleware.md b/docs/en/docs/advanced/middleware.md index d1be4afff..8deb0d917 100644 --- a/docs/en/docs/advanced/middleware.md +++ b/docs/en/docs/advanced/middleware.md @@ -94,4 +94,4 @@ For example: * Uvicorn's `ProxyHeadersMiddleware` * MessagePack -To see other available middlewares check Starlette's Middleware docs and the ASGI Awesome List. +To see other available middlewares check Starlette's Middleware docs and the ASGI Awesome List. diff --git a/docs/en/docs/advanced/response-cookies.md b/docs/en/docs/advanced/response-cookies.md index d8f77b56a..1f41d84b7 100644 --- a/docs/en/docs/advanced/response-cookies.md +++ b/docs/en/docs/advanced/response-cookies.md @@ -48,4 +48,4 @@ And as the `Response` can be used frequently to set headers and cookies, **FastA /// -To see all the available parameters and options, check the documentation in Starlette. +To see all the available parameters and options, check the documentation in Starlette. diff --git a/docs/en/docs/advanced/response-headers.md b/docs/en/docs/advanced/response-headers.md index 19c9ff2ad..855ba05f8 100644 --- a/docs/en/docs/advanced/response-headers.md +++ b/docs/en/docs/advanced/response-headers.md @@ -38,4 +38,4 @@ And as the `Response` can be used frequently to set headers and cookies, **FastA Keep in mind that custom proprietary headers can be added using the `X-` prefix. -But if you have custom headers that you want a client in a browser to be able to see, you need to add them to your CORS configurations (read more in [CORS (Cross-Origin Resource Sharing)](../tutorial/cors.md){.internal-link target=_blank}), using the parameter `expose_headers` documented in Starlette's CORS docs. +But if you have custom headers that you want a client in a browser to be able to see, you need to add them to your CORS configurations (read more in [CORS (Cross-Origin Resource Sharing)](../tutorial/cors.md){.internal-link target=_blank}), using the parameter `expose_headers` documented in Starlette's CORS docs. diff --git a/docs/en/docs/advanced/templates.md b/docs/en/docs/advanced/templates.md index f41c47fe8..356f4d9ca 100644 --- a/docs/en/docs/advanced/templates.md +++ b/docs/en/docs/advanced/templates.md @@ -123,4 +123,4 @@ And because you are using `StaticFiles`, that CSS file would be served automatic ## More details { #more-details } -For more details, including how to test templates, check Starlette's docs on templates. +For more details, including how to test templates, check Starlette's docs on templates. diff --git a/docs/en/docs/advanced/testing-events.md b/docs/en/docs/advanced/testing-events.md index cb8881a09..dd93374c4 100644 --- a/docs/en/docs/advanced/testing-events.md +++ b/docs/en/docs/advanced/testing-events.md @@ -5,7 +5,7 @@ When you need `lifespan` to run in your tests, you can use the `TestClient` with {* ../../docs_src/app_testing/tutorial004.py hl[9:15,18,27:28,30:32,41:43] *} -You can read more details about the ["Running lifespan in tests in the official Starlette documentation site."](https://www.starlette.io/lifespan/#running-lifespan-in-tests) +You can read more details about the ["Running lifespan in tests in the official Starlette documentation site."](https://www.starlette.dev/lifespan/#running-lifespan-in-tests) For the deprecated `startup` and `shutdown` events, you can use the `TestClient` as follows: diff --git a/docs/en/docs/advanced/testing-websockets.md b/docs/en/docs/advanced/testing-websockets.md index 22f9bb4a0..27eb2de2f 100644 --- a/docs/en/docs/advanced/testing-websockets.md +++ b/docs/en/docs/advanced/testing-websockets.md @@ -8,6 +8,6 @@ For this, you use the `TestClient` in a `with` statement, connecting to the WebS /// note -For more details, check Starlette's documentation for testing WebSockets. +For more details, check Starlette's documentation for testing WebSockets. /// diff --git a/docs/en/docs/advanced/using-request-directly.md b/docs/en/docs/advanced/using-request-directly.md index e412ad462..c71d3b05d 100644 --- a/docs/en/docs/advanced/using-request-directly.md +++ b/docs/en/docs/advanced/using-request-directly.md @@ -15,7 +15,7 @@ But there are situations where you might need to access the `Request` object dir ## Details about the `Request` object { #details-about-the-request-object } -As **FastAPI** is actually **Starlette** underneath, with a layer of several tools on top, you can use Starlette's `Request` object directly when you need to. +As **FastAPI** is actually **Starlette** underneath, with a layer of several tools on top, you can use Starlette's `Request` object directly when you need to. It would also mean that if you get data from the `Request` object directly (for example, read the body) it won't be validated, converted or documented (with OpenAPI, for the automatic API user interface) by FastAPI. @@ -45,7 +45,7 @@ The same way, you can declare any other parameter as normally, and additionally, ## `Request` documentation { #request-documentation } -You can read more details about the `Request` object in the official Starlette documentation site. +You can read more details about the `Request` object in the official Starlette documentation site. /// note | Technical Details diff --git a/docs/en/docs/advanced/websockets.md b/docs/en/docs/advanced/websockets.md index 917dd79bd..ce11485a8 100644 --- a/docs/en/docs/advanced/websockets.md +++ b/docs/en/docs/advanced/websockets.md @@ -182,5 +182,5 @@ If you need something easy to integrate with FastAPI but that is more robust, su To learn more about the options, check Starlette's documentation for: -* The `WebSocket` class. -* Class-based WebSocket handling. +* The `WebSocket` class. +* Class-based WebSocket handling. diff --git a/docs/en/docs/alternatives.md b/docs/en/docs/alternatives.md index f0576bc47..e65681543 100644 --- a/docs/en/docs/alternatives.md +++ b/docs/en/docs/alternatives.md @@ -417,7 +417,7 @@ Handle all the data validation, data serialization and automatic model documenta /// -### Starlette { #starlette } +### Starlette { #starlette } Starlette is a lightweight ASGI framework/toolkit, which is ideal for building high-performance asyncio services. @@ -462,7 +462,7 @@ So, anything that you can do with Starlette, you can do it directly with **FastA /// -### Uvicorn { #uvicorn } +### Uvicorn { #uvicorn } Uvicorn is a lightning-fast ASGI server, built on uvloop and httptools. diff --git a/docs/en/docs/deployment/manually.md b/docs/en/docs/deployment/manually.md index 8bb3945bc..311efb99f 100644 --- a/docs/en/docs/deployment/manually.md +++ b/docs/en/docs/deployment/manually.md @@ -52,7 +52,7 @@ The main thing you need to run a **FastAPI** application (or any other ASGI appl There are several alternatives, including: -* Uvicorn: a high performance ASGI server. +* Uvicorn: a high performance ASGI server. * Hypercorn: an ASGI server compatible with HTTP/2 and Trio among other features. * Daphne: the ASGI server built for Django Channels. * Granian: A Rust HTTP server for Python applications. diff --git a/docs/en/docs/fastapi-cli.md b/docs/en/docs/fastapi-cli.md index 0fb7789db..3e5f4e350 100644 --- a/docs/en/docs/fastapi-cli.md +++ b/docs/en/docs/fastapi-cli.md @@ -52,7 +52,7 @@ FastAPI CLI takes the path to your Python program (e.g. `main.py`) and automatic For production you would use `fastapi run` instead. 🚀 -Internally, **FastAPI CLI** uses Uvicorn, a high-performance, production-ready, ASGI server. 😎 +Internally, **FastAPI CLI** uses Uvicorn, a high-performance, production-ready, ASGI server. 😎 ## `fastapi dev` { #fastapi-dev } diff --git a/docs/en/docs/features.md b/docs/en/docs/features.md index d44d7a6ac..a345e4a0e 100644 --- a/docs/en/docs/features.md +++ b/docs/en/docs/features.md @@ -159,7 +159,7 @@ Any integration is designed to be so simple to use (with dependencies) that you ## Starlette features { #starlette-features } -**FastAPI** is fully compatible with (and based on) Starlette. So, any additional Starlette code you have, will also work. +**FastAPI** is fully compatible with (and based on) Starlette. So, any additional Starlette code you have, will also work. `FastAPI` is actually a sub-class of `Starlette`. So, if you already know or use Starlette, most of the functionality will work the same way. diff --git a/docs/en/docs/history-design-future.md b/docs/en/docs/history-design-future.md index 2182c415c..6175dcbbe 100644 --- a/docs/en/docs/history-design-future.md +++ b/docs/en/docs/history-design-future.md @@ -58,7 +58,7 @@ After testing several alternatives, I decided that I was going to use **Starlette**, the other key requirement. +During the development, I also contributed to **Starlette**, the other key requirement. ## Development { #development } diff --git a/docs/en/docs/how-to/custom-request-and-route.md b/docs/en/docs/how-to/custom-request-and-route.md index 6df24a080..884c8ed04 100644 --- a/docs/en/docs/how-to/custom-request-and-route.md +++ b/docs/en/docs/how-to/custom-request-and-route.md @@ -66,7 +66,7 @@ The `scope` `dict` and `receive` function are both part of the ASGI specificatio And those two things, `scope` and `receive`, are what is needed to create a new `Request` instance. -To learn more about the `Request` check Starlette's docs about Requests. +To learn more about the `Request` check Starlette's docs about Requests. /// diff --git a/docs/en/docs/img/sponsors/requestly.png b/docs/en/docs/img/sponsors/requestly.png new file mode 100644 index 000000000..a167aa017 Binary files /dev/null and b/docs/en/docs/img/sponsors/requestly.png differ diff --git a/docs/en/docs/img/sponsors/serpapi-banner.png b/docs/en/docs/img/sponsors/serpapi-banner.png new file mode 100644 index 000000000..3c3fd629e Binary files /dev/null and b/docs/en/docs/img/sponsors/serpapi-banner.png differ diff --git a/docs/en/docs/img/sponsors/serpapi.png b/docs/en/docs/img/sponsors/serpapi.png new file mode 100644 index 000000000..d7258ef70 Binary files /dev/null and b/docs/en/docs/img/sponsors/serpapi.png differ diff --git a/docs/en/docs/index.md b/docs/en/docs/index.md index aaadf3cc2..35c46d15f 100644 --- a/docs/en/docs/index.md +++ b/docs/en/docs/index.md @@ -123,7 +123,7 @@ If you are building a CLI app to be FastAPI stands on the shoulders of giants: -* Starlette for the web parts. +* Starlette for the web parts. * Pydantic for the data parts. ## Installation { #installation } @@ -229,7 +229,7 @@ INFO: Application startup complete.
About the command fastapi dev main.py... -The command `fastapi dev` reads your `main.py` file, detects the **FastAPI** app in it, and starts a server using Uvicorn. +The command `fastapi dev` reads your `main.py` file, detects the **FastAPI** app in it, and starts a server using Uvicorn. By default, `fastapi dev` will start with auto-reload enabled for local development. @@ -470,7 +470,7 @@ Used by Starlette: Used by FastAPI: -* uvicorn - for the server that loads and serves your application. This includes `uvicorn[standard]`, which includes some dependencies (e.g. `uvloop`) needed for high performance serving. +* uvicorn - for the server that loads and serves your application. This includes `uvicorn[standard]`, which includes some dependencies (e.g. `uvloop`) needed for high performance serving. * `fastapi-cli[standard]` - to provide the `fastapi` command. * This includes `fastapi-cloud-cli`, which allows you to deploy your FastAPI application to FastAPI Cloud. diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 663e99a23..9380fb7d4 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -7,6 +7,106 @@ hide: ## Latest Changes +### Docs + +* 📝 Upate docs for advanced dependencies with `yield`, noting the changes in 0.121.0, adding `scope`. PR [#14287](https://github.com/fastapi/fastapi/pull/14287) by [@tiangolo](https://github.com/tiangolo). + +### Internal + +* ⬆ Bump ruff from 0.13.2 to 0.14.3. PR [#14276](https://github.com/fastapi/fastapi/pull/14276) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#14289](https://github.com/fastapi/fastapi/pull/14289) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). + +## 0.121.0 + +### Features + +* ✨ Add support for dependencies with scopes, support `scope="request"` for dependencies with `yield` that exit before the response is sent. PR [#14262](https://github.com/fastapi/fastapi/pull/14262) by [@tiangolo](https://github.com/tiangolo). + * New docs: [Dependencies with `yield` - Early exit and `scope`](https://fastapi.tiangolo.com/tutorial/dependencies/dependencies-with-yield/#early-exit-and-scope). + +### Internal + +* 👥 Update FastAPI People - Contributors and Translators. PR [#14273](https://github.com/fastapi/fastapi/pull/14273) by [@tiangolo](https://github.com/tiangolo). +* 👥 Update FastAPI People - Sponsors. PR [#14274](https://github.com/fastapi/fastapi/pull/14274) by [@tiangolo](https://github.com/tiangolo). +* 👥 Update FastAPI GitHub topic repositories. PR [#14280](https://github.com/fastapi/fastapi/pull/14280) by [@tiangolo](https://github.com/tiangolo). +* ⬆ Bump mkdocs-macros-plugin from 1.4.0 to 1.4.1. PR [#14277](https://github.com/fastapi/fastapi/pull/14277) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump mkdocstrings[python] from 0.26.1 to 0.30.1. PR [#14279](https://github.com/fastapi/fastapi/pull/14279) by [@dependabot[bot]](https://github.com/apps/dependabot). + +## 0.120.4 + +### Fixes + +* 🐛 Fix security schemes in OpenAPI when added at the top level app. PR [#14266](https://github.com/fastapi/fastapi/pull/14266) by [@YuriiMotov](https://github.com/YuriiMotov). + +## 0.120.3 + +### Refactors + +* ♻️ Reduce internal cyclic recursion in dependencies, from 2 functions calling each other to 1 calling itself. PR [#14256](https://github.com/fastapi/fastapi/pull/14256) by [@tiangolo](https://github.com/tiangolo). +* ♻️ Refactor internals of dependencies, simplify code and remove `get_param_sub_dependant`. PR [#14255](https://github.com/fastapi/fastapi/pull/14255) by [@tiangolo](https://github.com/tiangolo). +* ♻️ Refactor internals of dependencies, simplify using dataclasses. PR [#14254](https://github.com/fastapi/fastapi/pull/14254) by [@tiangolo](https://github.com/tiangolo). + +### Docs + +* 📝 Update note for untranslated pages. PR [#14257](https://github.com/fastapi/fastapi/pull/14257) by [@YuriiMotov](https://github.com/YuriiMotov). + +## 0.120.2 + +### Fixes + +* 🐛 Fix separation of schemas with nested models introduced in 0.119.0. PR [#14246](https://github.com/fastapi/fastapi/pull/14246) by [@tiangolo](https://github.com/tiangolo). + +### Internal + +* 🔧 Add sponsor: SerpApi. PR [#14248](https://github.com/fastapi/fastapi/pull/14248) by [@tiangolo](https://github.com/tiangolo). +* ⬆ Bump actions/download-artifact from 5 to 6. PR [#14236](https://github.com/fastapi/fastapi/pull/14236) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#14237](https://github.com/fastapi/fastapi/pull/14237) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). +* ⬆ Bump actions/upload-artifact from 4 to 5. PR [#14235](https://github.com/fastapi/fastapi/pull/14235) by [@dependabot[bot]](https://github.com/apps/dependabot). + +## 0.120.1 + +### Upgrades + +* ⬆️ Bump Starlette to <`0.50.0`. PR [#14234](https://github.com/fastapi/fastapi/pull/14234) by [@YuriiMotov](https://github.com/YuriiMotov). + +### Internal + +* 🔧 Add `license` and `license-files` to `pyproject.toml`, remove `License` from `classifiers`. PR [#14230](https://github.com/fastapi/fastapi/pull/14230) by [@YuriiMotov](https://github.com/YuriiMotov). + +## 0.120.0 + +There are no major nor breaking changes in this release. ☕️ + +The internal reference documentation now uses `annotated_doc.Doc` instead of `typing_extensions.Doc`, this adds a new (very small) dependency on [`annotated-doc`](https://github.com/fastapi/annotated-doc), a package made just to provide that `Doc` documentation utility class. + +I would expect `typing_extensions.Doc` to be deprecated and then removed at some point from `typing_extensions`, for that reason there's the new `annotated-doc` micro-package. If you are curious about this, you can read more in the repo for [`annotated-doc`](https://github.com/fastapi/annotated-doc). + +This new version `0.120.0` only contains that transition to the new home package for that utility class `Doc`. + +### Translations + +* 🌐 Sync German docs. PR [#14188](https://github.com/fastapi/fastapi/pull/14188) by [@nilslindemann](https://github.com/nilslindemann). + +### Internal + +* ➕ Migrate internal reference documentation from `typing_extensions.Doc` to `annotated_doc.Doc`. PR [#14222](https://github.com/fastapi/fastapi/pull/14222) by [@tiangolo](https://github.com/tiangolo). +* 🛠️ Update German LLM prompt and test file. PR [#14189](https://github.com/fastapi/fastapi/pull/14189) by [@nilslindemann](https://github.com/nilslindemann). +* ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#14181](https://github.com/fastapi/fastapi/pull/14181) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). + +## 0.119.1 + +### Fixes + +* 🐛 Fix internal Pydantic v1 compatibility (warnings) for Python 3.14 and Pydantic 2.12.1. PR [#14186](https://github.com/fastapi/fastapi/pull/14186) by [@svlandeg](https://github.com/svlandeg). + +### Docs + +* 📝 Replace `starlette.io` by `starlette.dev` and `uvicorn.org` by `uvicorn.dev`. PR [#14176](https://github.com/fastapi/fastapi/pull/14176) by [@Kludex](https://github.com/Kludex). + +### Internal + +* 🔧 Add sponsor Requestly. PR [#14205](https://github.com/fastapi/fastapi/pull/14205) by [@tiangolo](https://github.com/tiangolo). +* 🔧 Configure reminder for `waiting` label in `issue-manager`. PR [#14156](https://github.com/fastapi/fastapi/pull/14156) by [@YuriiMotov](https://github.com/YuriiMotov). + ## 0.119.0 FastAPI now (temporarily) supports both Pydantic v2 models and `pydantic.v1` models at the same time in the same app, to make it easier for any FastAPI apps still using Pydantic v1 to gradually but quickly **migrate to Pydantic v2**. @@ -5526,7 +5626,7 @@ Note: all the previous parameters are still there, so it's still possible to dec * Upgrade the compatible version of Starlette to `0.12.0`. * This includes support for ASGI 3 (the latest version of the standard). - * It's now possible to use [Starlette's `StreamingResponse`](https://www.starlette.io/responses/#streamingresponse) with iterators, like [file-like](https://docs.python.org/3/glossary.html#term-file-like-object) objects (as those returned by `open()`). + * It's now possible to use [Starlette's `StreamingResponse`](https://www.starlette.dev/responses/#streamingresponse) with iterators, like [file-like](https://docs.python.org/3/glossary.html#term-file-like-object) objects (as those returned by `open()`). * It's now possible to use the low level utility `iterate_in_threadpool` from `starlette.concurrency` (for advanced scenarios). * PR [#243](https://github.com/tiangolo/fastapi/pull/243). diff --git a/docs/en/docs/tutorial/background-tasks.md b/docs/en/docs/tutorial/background-tasks.md index 6e16410a3..ab44f89c1 100644 --- a/docs/en/docs/tutorial/background-tasks.md +++ b/docs/en/docs/tutorial/background-tasks.md @@ -63,7 +63,7 @@ And then another background task generated at the *path operation function* will ## Technical Details { #technical-details } -The class `BackgroundTasks` comes directly from `starlette.background`. +The class `BackgroundTasks` comes directly from `starlette.background`. It is imported/included directly into FastAPI so that you can import it from `fastapi` and avoid accidentally importing the alternative `BackgroundTask` (without the `s` at the end) from `starlette.background`. @@ -71,7 +71,7 @@ By only using `BackgroundTasks` (and not `BackgroundTask`), it's then possible t It's still possible to use `BackgroundTask` alone in FastAPI, but you have to create the object in your code and return a Starlette `Response` including it. -You can see more details in Starlette's official docs for Background Tasks. +You can see more details in Starlette's official docs for Background Tasks. ## Caveat { #caveat } diff --git a/docs/en/docs/tutorial/dependencies/dependencies-with-yield.md b/docs/en/docs/tutorial/dependencies/dependencies-with-yield.md index adc1afa8d..494c40efa 100644 --- a/docs/en/docs/tutorial/dependencies/dependencies-with-yield.md +++ b/docs/en/docs/tutorial/dependencies/dependencies-with-yield.md @@ -184,6 +184,51 @@ If you raise any exception in the code from the *path operation function*, it wi /// +## Early exit and `scope` { #early-exit-and-scope } + +Normally the exit code of dependencies with `yield` is executed **after the response** is sent to the client. + +But if you know that you won't need to use the dependency after returning from the *path operation function*, you can use `Depends(scope="function")` to tell FastAPI that it should close the dependency after the *path operation function* returns, but **before** the **response is sent**. + +{* ../../docs_src/dependencies/tutorial008e_an_py39.py hl[12,16] *} + +`Depends()` receives a `scope` parameter that can be: + +* `"function"`: start the dependency before the *path operation function* that handles the request, end the dependency after the *path operation function* ends, but **before** the response is sent back to the client. So, the dependency function will be executed **around** the *path operation **function***. +* `"request"`: start the dependency before the *path operation function* that handles the request (similar to when using `"function"`), but end **after** the response is sent back to the client. So, the dependency function will be executed **around** the **request** and response cycle. + +If not specified and the dependency has `yield`, it will have a `scope` of `"request"` by default. + +### `scope` for sub-dependencies { #scope-for-sub-dependencies } + +When you declare a dependency with a `scope="request"` (the default), any sub-dependency needs to also have a `scope` of `"request"`. + +But a dependency with `scope` of `"function"` can have dependencies with `scope` of `"function"` and `scope` of `"request"`. + +This is because any dependency needs to be able to run its exit code before the sub-dependencies, as it might need to still use them during its exit code. + +```mermaid +sequenceDiagram + +participant client as Client +participant dep_req as Dep scope="request" +participant dep_func as Dep scope="function" +participant operation as Path Operation + + client ->> dep_req: Start request + Note over dep_req: Run code up to yield + dep_req ->> dep_func: Pass dependency + Note over dep_func: Run code up to yield + dep_func ->> operation: Run path operation with dependency + operation ->> dep_func: Return from path operation + Note over dep_func: Run code after yield + Note over dep_func: ✅ Dependency closed + dep_func ->> client: Send response to client + Note over client: Response sent + Note over dep_req: Run code after yield + Note over dep_req: ✅ Dependency closed +``` + ## Dependencies with `yield`, `HTTPException`, `except` and Background Tasks { #dependencies-with-yield-httpexception-except-and-background-tasks } Dependencies with `yield` have evolved over time to cover different use cases and fix some issues. diff --git a/docs/en/docs/tutorial/first-steps.md b/docs/en/docs/tutorial/first-steps.md index e75e40991..7d4c12de8 100644 --- a/docs/en/docs/tutorial/first-steps.md +++ b/docs/en/docs/tutorial/first-steps.md @@ -155,7 +155,7 @@ You could also use it to generate code automatically, for clients that communica `FastAPI` is a class that inherits directly from `Starlette`. -You can use all the Starlette functionality with `FastAPI` too. +You can use all the Starlette functionality with `FastAPI` too. /// diff --git a/docs/en/docs/tutorial/handling-errors.md b/docs/en/docs/tutorial/handling-errors.md index 58bf8ffa7..53501837c 100644 --- a/docs/en/docs/tutorial/handling-errors.md +++ b/docs/en/docs/tutorial/handling-errors.md @@ -81,7 +81,7 @@ But in case you needed it for an advanced scenario, you can add custom headers: ## Install custom exception handlers { #install-custom-exception-handlers } -You can add custom exception handlers with the same exception utilities from Starlette. +You can add custom exception handlers with the same exception utilities from Starlette. Let's say you have a custom exception `UnicornException` that you (or a library you use) might `raise`. diff --git a/docs/en/docs/tutorial/middleware.md b/docs/en/docs/tutorial/middleware.md index bc0519c67..d8889fc63 100644 --- a/docs/en/docs/tutorial/middleware.md +++ b/docs/en/docs/tutorial/middleware.md @@ -37,7 +37,7 @@ The middleware function receives: Keep in mind that custom proprietary headers can be added using the `X-` prefix. -But if you have custom headers that you want a client in a browser to be able to see, you need to add them to your CORS configurations ([CORS (Cross-Origin Resource Sharing)](cors.md){.internal-link target=_blank}) using the parameter `expose_headers` documented in Starlette's CORS docs. +But if you have custom headers that you want a client in a browser to be able to see, you need to add them to your CORS configurations ([CORS (Cross-Origin Resource Sharing)](cors.md){.internal-link target=_blank}) using the parameter `expose_headers` documented in Starlette's CORS docs. /// diff --git a/docs/en/docs/tutorial/static-files.md b/docs/en/docs/tutorial/static-files.md index 5b75d048b..66b934d4f 100644 --- a/docs/en/docs/tutorial/static-files.md +++ b/docs/en/docs/tutorial/static-files.md @@ -37,4 +37,4 @@ All these parameters can be different than "`static`", adjust them with the need ## More info { #more-info } -For more details and options check Starlette's docs about Static Files. +For more details and options check Starlette's docs about Static Files. diff --git a/docs/en/docs/tutorial/testing.md b/docs/en/docs/tutorial/testing.md index 1e333c8f1..3dcf5dc4a 100644 --- a/docs/en/docs/tutorial/testing.md +++ b/docs/en/docs/tutorial/testing.md @@ -1,6 +1,6 @@ # Testing { #testing } -Thanks to Starlette, testing **FastAPI** applications is easy and enjoyable. +Thanks to Starlette, testing **FastAPI** applications is easy and enjoyable. It is based on HTTPX, which in turn is designed based on Requests, so it's very familiar and intuitive. diff --git a/docs/en/overrides/main.html b/docs/en/overrides/main.html index c7ffaef5d..be31bd75c 100644 --- a/docs/en/overrides/main.html +++ b/docs/en/overrides/main.html @@ -80,6 +80,12 @@
+ {% endblock %} diff --git a/docs/es/docs/advanced/events.md b/docs/es/docs/advanced/events.md index 022fb5a42..a33b51791 100644 --- a/docs/es/docs/advanced/events.md +++ b/docs/es/docs/advanced/events.md @@ -154,7 +154,7 @@ Por debajo, en la especificación técnica ASGI, esto es parte del la documentación de `Lifespan` de Starlette. +Puedes leer más sobre los manejadores `lifespan` de Starlette en la documentación de `Lifespan` de Starlette. Incluyendo cómo manejar el estado de lifespan que puede ser usado en otras áreas de tu código. diff --git a/docs/es/docs/advanced/middleware.md b/docs/es/docs/advanced/middleware.md index b8fd86185..0c8c44b88 100644 --- a/docs/es/docs/advanced/middleware.md +++ b/docs/es/docs/advanced/middleware.md @@ -93,4 +93,4 @@ Por ejemplo: * `ProxyHeadersMiddleware` de Uvicorn * MessagePack -Para ver otros middlewares disponibles, revisa la documentación de Middleware de Starlette y la Lista ASGI Awesome. +Para ver otros middlewares disponibles, revisa la documentación de Middleware de Starlette y la Lista ASGI Awesome. diff --git a/docs/es/docs/advanced/response-cookies.md b/docs/es/docs/advanced/response-cookies.md index c4472eaa1..05b78528e 100644 --- a/docs/es/docs/advanced/response-cookies.md +++ b/docs/es/docs/advanced/response-cookies.md @@ -48,4 +48,4 @@ Y como el `Response` se puede usar frecuentemente para establecer headers y cook /// -Para ver todos los parámetros y opciones disponibles, revisa la documentación en Starlette. +Para ver todos los parámetros y opciones disponibles, revisa la documentación en Starlette. diff --git a/docs/es/docs/advanced/response-headers.md b/docs/es/docs/advanced/response-headers.md index 49eaa53c1..31a135c40 100644 --- a/docs/es/docs/advanced/response-headers.md +++ b/docs/es/docs/advanced/response-headers.md @@ -38,4 +38,4 @@ Y como el `Response` se puede usar frecuentemente para establecer headers y cook Ten en cuenta que los headers propietarios personalizados se pueden agregar usando el prefijo 'X-'. -Pero si tienes headers personalizados que quieres que un cliente en un navegador pueda ver, necesitas agregarlos a tus configuraciones de CORS (leer más en [CORS (Cross-Origin Resource Sharing)](../tutorial/cors.md){.internal-link target=_blank}), usando el parámetro `expose_headers` documentado en la documentación CORS de Starlette. +Pero si tienes headers personalizados que quieres que un cliente en un navegador pueda ver, necesitas agregarlos a tus configuraciones de CORS (leer más en [CORS (Cross-Origin Resource Sharing)](../tutorial/cors.md){.internal-link target=_blank}), usando el parámetro `expose_headers` documentado en la documentación CORS de Starlette. diff --git a/docs/es/docs/advanced/templates.md b/docs/es/docs/advanced/templates.md index 9de866c2b..101819737 100644 --- a/docs/es/docs/advanced/templates.md +++ b/docs/es/docs/advanced/templates.md @@ -123,4 +123,4 @@ Y porque estás usando `StaticFiles`, ese archivo CSS sería servido automática ## Más detalles -Para más detalles, incluyendo cómo testear plantillas, revisa la documentación de Starlette sobre plantillas. +Para más detalles, incluyendo cómo testear plantillas, revisa la documentación de Starlette sobre plantillas. diff --git a/docs/es/docs/advanced/testing-websockets.md b/docs/es/docs/advanced/testing-websockets.md index 6d2eaf94d..190e3a224 100644 --- a/docs/es/docs/advanced/testing-websockets.md +++ b/docs/es/docs/advanced/testing-websockets.md @@ -8,6 +8,6 @@ Para esto, usas el `TestClient` en un statement `with`, conectándote al WebSock /// note | Nota -Para más detalles, revisa la documentación de Starlette sobre probando sesiones WebSocket. +Para más detalles, revisa la documentación de Starlette sobre probando sesiones WebSocket. /// diff --git a/docs/es/docs/advanced/using-request-directly.md b/docs/es/docs/advanced/using-request-directly.md index be8afffcc..f61e49849 100644 --- a/docs/es/docs/advanced/using-request-directly.md +++ b/docs/es/docs/advanced/using-request-directly.md @@ -15,7 +15,7 @@ Pero hay situaciones donde podrías necesitar acceder al objeto `Request` direct ## Detalles sobre el objeto `Request` -Como **FastAPI** es en realidad **Starlette** por debajo, con una capa de varias herramientas encima, puedes usar el objeto `Request` de Starlette directamente cuando lo necesites. +Como **FastAPI** es en realidad **Starlette** por debajo, con una capa de varias herramientas encima, puedes usar el objeto `Request` de Starlette directamente cuando lo necesites. También significa que si obtienes datos del objeto `Request` directamente (por ejemplo, leyendo el cuerpo) no serán validados, convertidos o documentados (con OpenAPI, para la interfaz automática de usuario de la API) por FastAPI. @@ -45,7 +45,7 @@ De la misma manera, puedes declarar cualquier otro parámetro como normalmente, ## Documentación de `Request` -Puedes leer más detalles sobre el objeto `Request` en el sitio de documentación oficial de Starlette. +Puedes leer más detalles sobre el objeto `Request` en el sitio de documentación oficial de Starlette. /// note | Detalles Técnicos diff --git a/docs/es/docs/advanced/websockets.md b/docs/es/docs/advanced/websockets.md index 95141c1ca..1320f8bb7 100644 --- a/docs/es/docs/advanced/websockets.md +++ b/docs/es/docs/advanced/websockets.md @@ -182,5 +182,5 @@ Si necesitas algo fácil de integrar con FastAPI pero que sea más robusto, sopo Para aprender más sobre las opciones, revisa la documentación de Starlette para: -* La clase `WebSocket`. -* Manejo de WebSocket basado en clases. +* La clase `WebSocket`. +* Manejo de WebSocket basado en clases. diff --git a/docs/es/docs/alternatives.md b/docs/es/docs/alternatives.md index 753b827c0..6605b7bb0 100644 --- a/docs/es/docs/alternatives.md +++ b/docs/es/docs/alternatives.md @@ -417,7 +417,7 @@ Manejar toda la validación de datos, serialización de datos y documentación a /// -### Starlette +### Starlette Starlette es un framework/toolkit ASGI liviano, ideal para construir servicios asyncio de alto rendimiento. @@ -462,7 +462,7 @@ Por lo tanto, cualquier cosa que puedas hacer con Starlette, puedes hacerlo dire /// -### Uvicorn +### Uvicorn Uvicorn es un servidor ASGI extremadamente rápido, construido sobre uvloop y httptools. diff --git a/docs/es/docs/deployment/manually.md b/docs/es/docs/deployment/manually.md index 509b9ebdb..b56cf9514 100644 --- a/docs/es/docs/deployment/manually.md +++ b/docs/es/docs/deployment/manually.md @@ -64,7 +64,7 @@ Lo principal que necesitas para ejecutar una aplicación **FastAPI** (o cualquie Hay varias alternativas, incluyendo: -* Uvicorn: un servidor ASGI de alto rendimiento. +* Uvicorn: un servidor ASGI de alto rendimiento. * Hypercorn: un servidor ASGI compatible con HTTP/2 y Trio entre otras funcionalidades. * Daphne: el servidor ASGI construido para Django Channels. * Granian: Un servidor HTTP Rust para aplicaciones en Python. diff --git a/docs/es/docs/fastapi-cli.md b/docs/es/docs/fastapi-cli.md index 9d7629fdb..34b18ee3d 100644 --- a/docs/es/docs/fastapi-cli.md +++ b/docs/es/docs/fastapi-cli.md @@ -52,7 +52,7 @@ FastAPI CLI toma el path de tu programa Python (por ejemplo, `main.py`), detecta Para producción usarías `fastapi run` en su lugar. 🚀 -Internamente, **FastAPI CLI** usa Uvicorn, un servidor ASGI de alto rendimiento y listo para producción. 😎 +Internamente, **FastAPI CLI** usa Uvicorn, un servidor ASGI de alto rendimiento y listo para producción. 😎 ## `fastapi dev` diff --git a/docs/es/docs/features.md b/docs/es/docs/features.md index 472fdd736..ac73bee16 100644 --- a/docs/es/docs/features.md +++ b/docs/es/docs/features.md @@ -159,7 +159,7 @@ Cualquier integración está diseñada para ser tan simple de usar (con dependen ## Funcionalidades de Starlette -**FastAPI** es totalmente compatible con (y está basado en) Starlette. Así que, cualquier código adicional de Starlette que tengas, también funcionará. +**FastAPI** es totalmente compatible con (y está basado en) Starlette. Así que, cualquier código adicional de Starlette que tengas, también funcionará. `FastAPI` es en realidad una subclase de `Starlette`. Así que, si ya conoces o usas Starlette, la mayoría de las funcionalidades funcionarán de la misma manera. diff --git a/docs/es/docs/history-design-future.md b/docs/es/docs/history-design-future.md index 8beb4f400..7ed4fdf05 100644 --- a/docs/es/docs/history-design-future.md +++ b/docs/es/docs/history-design-future.md @@ -58,7 +58,7 @@ Después de probar varias alternativas, decidí que iba a usar **Starlette**, el otro requisito clave. +Durante el desarrollo, también contribuí a **Starlette**, el otro requisito clave. ## Desarrollo diff --git a/docs/es/docs/how-to/custom-request-and-route.md b/docs/es/docs/how-to/custom-request-and-route.md index 0b479bf00..a6ea657d1 100644 --- a/docs/es/docs/how-to/custom-request-and-route.md +++ b/docs/es/docs/how-to/custom-request-and-route.md @@ -66,7 +66,7 @@ El `dict` `scope` y la función `receive` son ambos parte de la especificación Y esas dos cosas, `scope` y `receive`, son lo que se necesita para crear una nueva *Request instance*. -Para aprender más sobre el `Request`, revisa la documentación de Starlette sobre Requests. +Para aprender más sobre el `Request`, revisa la documentación de Starlette sobre Requests. /// diff --git a/docs/es/docs/index.md b/docs/es/docs/index.md index 4c8c703b3..a965fa4b5 100644 --- a/docs/es/docs/index.md +++ b/docs/es/docs/index.md @@ -123,7 +123,7 @@ Si estás construyendo una aplicación de Starlette para las partes web. +* Starlette para las partes web. * Pydantic para las partes de datos. ## Instalación @@ -229,7 +229,7 @@ INFO: Application startup complete.
Acerca del comando fastapi dev main.py... -El comando `fastapi dev` lee tu archivo `main.py`, detecta la app **FastAPI** en él y arranca un servidor usando Uvicorn. +El comando `fastapi dev` lee tu archivo `main.py`, detecta la app **FastAPI** en él y arranca un servidor usando Uvicorn. Por defecto, `fastapi dev` comenzará con auto-recarga habilitada para el desarrollo local. @@ -470,7 +470,7 @@ Usadas por Starlette: Usadas por FastAPI / Starlette: -* uvicorn - para el servidor que carga y sirve tu aplicación. Esto incluye `uvicorn[standard]`, que incluye algunas dependencias (por ejemplo, `uvloop`) necesarias para servir con alto rendimiento. +* uvicorn - para el servidor que carga y sirve tu aplicación. Esto incluye `uvicorn[standard]`, que incluye algunas dependencias (por ejemplo, `uvloop`) necesarias para servir con alto rendimiento. * `fastapi-cli` - para proporcionar el comando `fastapi`. ### Sin Dependencias `standard` diff --git a/docs/es/docs/tutorial/background-tasks.md b/docs/es/docs/tutorial/background-tasks.md index 3fe961e41..783db20a4 100644 --- a/docs/es/docs/tutorial/background-tasks.md +++ b/docs/es/docs/tutorial/background-tasks.md @@ -61,7 +61,7 @@ Y luego otra tarea en segundo plano generada en la *path operation function* esc ## Detalles Técnicos -La clase `BackgroundTasks` proviene directamente de `starlette.background`. +La clase `BackgroundTasks` proviene directamente de `starlette.background`. Se importa/incluye directamente en FastAPI para que puedas importarla desde `fastapi` y evitar importar accidentalmente la alternativa `BackgroundTask` (sin la `s` al final) de `starlette.background`. @@ -69,7 +69,7 @@ Al usar solo `BackgroundTasks` (y no `BackgroundTask`), es posible usarla como u Todavía es posible usar `BackgroundTask` solo en FastAPI, pero debes crear el objeto en tu código y devolver una `Response` de Starlette incluyéndolo. -Puedes ver más detalles en la documentación oficial de Starlette sobre Background Tasks. +Puedes ver más detalles en la documentación oficial de Starlette sobre Background Tasks. ## Advertencia diff --git a/docs/es/docs/tutorial/first-steps.md b/docs/es/docs/tutorial/first-steps.md index 5d869c22f..b451782ad 100644 --- a/docs/es/docs/tutorial/first-steps.md +++ b/docs/es/docs/tutorial/first-steps.md @@ -163,7 +163,7 @@ También podrías usarlo para generar código automáticamente, para clientes qu `FastAPI` es una clase que hereda directamente de `Starlette`. -Puedes usar toda la funcionalidad de Starlette con `FastAPI` también. +Puedes usar toda la funcionalidad de Starlette con `FastAPI` también. /// diff --git a/docs/es/docs/tutorial/handling-errors.md b/docs/es/docs/tutorial/handling-errors.md index 2e4464989..107af2a70 100644 --- a/docs/es/docs/tutorial/handling-errors.md +++ b/docs/es/docs/tutorial/handling-errors.md @@ -81,7 +81,7 @@ Pero en caso de que los necesites para un escenario avanzado, puedes agregar hea ## Instalar manejadores de excepciones personalizados -Puedes agregar manejadores de excepciones personalizados con las mismas utilidades de excepciones de Starlette. +Puedes agregar manejadores de excepciones personalizados con las mismas utilidades de excepciones de Starlette. Supongamos que tienes una excepción personalizada `UnicornException` que tú (o un paquete que usas) podría lanzar. diff --git a/docs/es/docs/tutorial/middleware.md b/docs/es/docs/tutorial/middleware.md index 296374525..c42e4eaa5 100644 --- a/docs/es/docs/tutorial/middleware.md +++ b/docs/es/docs/tutorial/middleware.md @@ -37,7 +37,7 @@ La función middleware recibe: Ten en cuenta que los custom proprietary headers se pueden añadir usando el prefijo 'X-'. -Pero si tienes custom headers que deseas que un cliente en un navegador pueda ver, necesitas añadirlos a tus configuraciones de CORS ([CORS (Cross-Origin Resource Sharing)](cors.md){.internal-link target=_blank}) usando el parámetro `expose_headers` documentado en la documentación de CORS de Starlette. +Pero si tienes custom headers que deseas que un cliente en un navegador pueda ver, necesitas añadirlos a tus configuraciones de CORS ([CORS (Cross-Origin Resource Sharing)](cors.md){.internal-link target=_blank}) usando el parámetro `expose_headers` documentado en la documentación de CORS de Starlette. /// diff --git a/docs/es/docs/tutorial/static-files.md b/docs/es/docs/tutorial/static-files.md index 6aefecc4b..8c5855d86 100644 --- a/docs/es/docs/tutorial/static-files.md +++ b/docs/es/docs/tutorial/static-files.md @@ -37,4 +37,4 @@ Todos estos parámetros pueden ser diferentes a "`static`", ajústalos según la ## Más info -Para más detalles y opciones revisa la documentación de Starlette sobre Archivos Estáticos. +Para más detalles y opciones revisa la documentación de Starlette sobre Archivos Estáticos. diff --git a/docs/es/docs/tutorial/testing.md b/docs/es/docs/tutorial/testing.md index 62ad89d58..c68e83ae3 100644 --- a/docs/es/docs/tutorial/testing.md +++ b/docs/es/docs/tutorial/testing.md @@ -1,6 +1,6 @@ # Testing -Gracias a Starlette, escribir pruebas para aplicaciones de **FastAPI** es fácil y agradable. +Gracias a Starlette, escribir pruebas para aplicaciones de **FastAPI** es fácil y agradable. Está basado en HTTPX, que a su vez está diseñado basado en Requests, por lo que es muy familiar e intuitivo. diff --git a/docs/fa/docs/features.md b/docs/fa/docs/features.md index a5ab1597e..c265d2970 100644 --- a/docs/fa/docs/features.md +++ b/docs/fa/docs/features.md @@ -167,7 +167,7 @@ FastAPI شامل یک سیستم Uvicorn : un serveur ASGI haute performance. +* Uvicorn : un serveur ASGI haute performance. * Hypercorn : un serveur ASGI compatible avec HTTP/2 et Trio entre autres fonctionnalités. * Daphne : le serveur ASGI @@ -27,7 +27,7 @@ Vous pouvez installer un serveur compatible ASGI avec : //// tab | Uvicorn -* Uvicorn, un serveur ASGI rapide comme l'éclair, basé sur uvloop et httptools. +* Uvicorn, un serveur ASGI rapide comme l'éclair, basé sur uvloop et httptools.
diff --git a/docs/fr/docs/features.md b/docs/fr/docs/features.md index afb1de243..bc63e11b4 100644 --- a/docs/fr/docs/features.md +++ b/docs/fr/docs/features.md @@ -158,7 +158,7 @@ Tout intégration est conçue pour être si simple à utiliser (avec des dépend ## Fonctionnalités de Starlette -**FastAPI** est complètement compatible (et basé sur) Starlette. Le code utilisant Starlette que vous ajouterez fonctionnera donc aussi. +**FastAPI** est complètement compatible (et basé sur) Starlette. Le code utilisant Starlette que vous ajouterez fonctionnera donc aussi. En fait, `FastAPI` est un sous composant de `Starlette`. Donc, si vous savez déjà comment utiliser Starlette, la plupart des fonctionnalités fonctionneront de la même manière. diff --git a/docs/fr/docs/history-design-future.md b/docs/fr/docs/history-design-future.md index 6b26dd079..15be545ee 100644 --- a/docs/fr/docs/history-design-future.md +++ b/docs/fr/docs/history-design-future.md @@ -58,7 +58,7 @@ Après avoir testé plusieurs alternatives, j'ai décidé que j'allais utiliser J'y ai ensuite contribué, pour le rendre entièrement compatible avec JSON Schema, pour supporter différentes manières de définir les déclarations de contraintes, et pour améliorer le support des éditeurs (vérifications de type, autocomplétion) sur la base des tests effectués dans plusieurs éditeurs. -Pendant le développement, j'ai également contribué à **Starlette**, l'autre exigence clé. +Pendant le développement, j'ai également contribué à **Starlette**, l'autre exigence clé. ## Développement diff --git a/docs/fr/docs/index.md b/docs/fr/docs/index.md index 015c9574a..99ea8dda1 100644 --- a/docs/fr/docs/index.md +++ b/docs/fr/docs/index.md @@ -123,7 +123,7 @@ Si vous souhaitez construire une application Starlette pour les parties web. +* Starlette pour les parties web. * Pydantic pour les parties données. ## Installation @@ -138,7 +138,7 @@ $ pip install fastapi
-Vous aurez également besoin d'un serveur ASGI pour la production tel que Uvicorn ou Hypercorn. +Vous aurez également besoin d'un serveur ASGI pour la production tel que Uvicorn ou Hypercorn.
@@ -461,7 +461,7 @@ Utilisées par Starlette : Utilisées par FastAPI / Starlette : -* uvicorn - Pour le serveur qui charge et sert votre application. +* uvicorn - Pour le serveur qui charge et sert votre application. * orjson - Obligatoire si vous voulez utiliser `ORJSONResponse`. * ujson - Obligatoire si vous souhaitez utiliser `UJSONResponse`. diff --git a/docs/fr/docs/tutorial/background-tasks.md b/docs/fr/docs/tutorial/background-tasks.md index 2065ca58e..6efd16e07 100644 --- a/docs/fr/docs/tutorial/background-tasks.md +++ b/docs/fr/docs/tutorial/background-tasks.md @@ -61,7 +61,7 @@ Et ensuite une autre tâche d'arrière-plan (générée dans les paramètres de ## Détails techniques -La classe `BackgroundTasks` provient directement de `starlette.background`. +La classe `BackgroundTasks` provient directement de `starlette.background`. Elle est importée/incluse directement dans **FastAPI** pour que vous puissiez l'importer depuis `fastapi` et éviter d'importer accidentellement `BackgroundTask` (sans `s` à la fin) depuis `starlette.background`. @@ -69,7 +69,7 @@ En utilisant seulement `BackgroundTasks` (et non `BackgroundTask`), il est possi Il est tout de même possible d'utiliser `BackgroundTask` seul dans **FastAPI**, mais dans ce cas il faut créer l'objet dans le code et renvoyer une `Response` Starlette l'incluant. -Plus de détails sont disponibles dans la documentation officielle de Starlette sur les tâches d'arrière-plan (via leurs classes `BackgroundTasks`et `BackgroundTask`). +Plus de détails sont disponibles dans la documentation officielle de Starlette sur les tâches d'arrière-plan (via leurs classes `BackgroundTasks`et `BackgroundTask`). ## Avertissement diff --git a/docs/fr/docs/tutorial/first-steps.md b/docs/fr/docs/tutorial/first-steps.md index 758145362..96ea56e62 100644 --- a/docs/fr/docs/tutorial/first-steps.md +++ b/docs/fr/docs/tutorial/first-steps.md @@ -140,7 +140,7 @@ Vous pourriez aussi l'utiliser pour générer du code automatiquement, pour les `FastAPI` est une classe héritant directement de `Starlette`. -Vous pouvez donc aussi utiliser toutes les fonctionnalités de Starlette depuis `FastAPI`. +Vous pouvez donc aussi utiliser toutes les fonctionnalités de Starlette depuis `FastAPI`. /// diff --git a/docs/ja/docs/advanced/websockets.md b/docs/ja/docs/advanced/websockets.md index 43009eba8..2517530ab 100644 --- a/docs/ja/docs/advanced/websockets.md +++ b/docs/ja/docs/advanced/websockets.md @@ -184,5 +184,5 @@ Client #1596980209979 left the chat オプションの詳細については、Starletteのドキュメントを確認してください。 -* `WebSocket` クラス -* クラスベースのWebSocket処理 +* `WebSocket` クラス +* クラスベースのWebSocket処理 diff --git a/docs/ja/docs/alternatives.md b/docs/ja/docs/alternatives.md index 8129a7002..9f5152c08 100644 --- a/docs/ja/docs/alternatives.md +++ b/docs/ja/docs/alternatives.md @@ -419,7 +419,7 @@ Marshmallowに匹敵しますが、ベンチマークではMarshmallowよりも /// -### Starlette +### Starlette Starletteは、軽量なASGIフレームワーク/ツールキットで、高性能な非同期サービスの構築に最適です。 @@ -465,7 +465,7 @@ webに関するコアな部分を全て扱います。その上に機能を追 /// -### Uvicorn +### Uvicorn Uvicornは非常に高速なASGIサーバーで、uvloopとhttptoolsにより構成されています。 diff --git a/docs/ja/docs/deployment/manually.md b/docs/ja/docs/deployment/manually.md index 4ea6bd8ff..da382a9c5 100644 --- a/docs/ja/docs/deployment/manually.md +++ b/docs/ja/docs/deployment/manually.md @@ -6,7 +6,7 @@ //// tab | Uvicorn -* Uvicorn, uvloopとhttptoolsを基にした高速なASGIサーバ。 +* Uvicorn, uvloopとhttptoolsを基にした高速なASGIサーバ。
@@ -78,7 +78,7 @@ Running on 0.0.0.0:8080 over http (CTRL + C to quit) 停止した場合に自動的に再起動させるツールを設定したいかもしれません。 -さらに、GunicornをインストールしてUvicornのマネージャーとして使用したり、複数のワーカーでHypercornを使用したいかもしれません。 +さらに、GunicornをインストールしてUvicornのマネージャーとして使用したり、複数のワーカーでHypercornを使用したいかもしれません。 ワーカー数などの微調整も行いたいかもしれません。 diff --git a/docs/ja/docs/features.md b/docs/ja/docs/features.md index 4024590cf..f78eab430 100644 --- a/docs/ja/docs/features.md +++ b/docs/ja/docs/features.md @@ -160,7 +160,7 @@ FastAPIには非常に使いやすく、非常に強力なしてカスタムの独自ヘッダーを追加できます。 -ただし、ブラウザのクライアントに表示させたいカスタムヘッダーがある場合は、StarletteのCORSドキュメントに記載されているパラメータ `expose_headers` を使用して、それらをCORS設定に追加する必要があります ([CORS (オリジン間リソース共有)](cors.md){.internal-link target=_blank}) +ただし、ブラウザのクライアントに表示させたいカスタムヘッダーがある場合は、StarletteのCORSドキュメントに記載されているパラメータ `expose_headers` を使用して、それらをCORS設定に追加する必要があります ([CORS (オリジン間リソース共有)](cors.md){.internal-link target=_blank}) /// diff --git a/docs/ja/docs/tutorial/static-files.md b/docs/ja/docs/tutorial/static-files.md index f63f3f3b1..f910d7e36 100644 --- a/docs/ja/docs/tutorial/static-files.md +++ b/docs/ja/docs/tutorial/static-files.md @@ -37,4 +37,4 @@ ## より詳しい情報 -詳細とオプションについては、Starletteの静的ファイルに関するドキュメントを確認してください。 +詳細とオプションについては、Starletteの静的ファイルに関するドキュメントを確認してください。 diff --git a/docs/ja/docs/tutorial/testing.md b/docs/ja/docs/tutorial/testing.md index fe6c8c6b4..4e8ad4f7c 100644 --- a/docs/ja/docs/tutorial/testing.md +++ b/docs/ja/docs/tutorial/testing.md @@ -1,6 +1,6 @@ # テスト -Starlette のおかげで、**FastAPI** アプリケーションのテストは簡単で楽しいものになっています。 +Starlette のおかげで、**FastAPI** アプリケーションのテストは簡単で楽しいものになっています。 HTTPX がベースなので、非常に使いやすく直感的です。 diff --git a/docs/ko/docs/advanced/events.md b/docs/ko/docs/advanced/events.md index 5f8fe0f1e..4318ada54 100644 --- a/docs/ko/docs/advanced/events.md +++ b/docs/ko/docs/advanced/events.md @@ -154,7 +154,7 @@ ASGI 기술 사양에 따르면, 이는 Starlette의 Lifespan 문서에서 확인할 수 있습니다. +Starlette의 `lifespan` 핸들러에 대해 더 읽고 싶다면 Starlette의 Lifespan 문서에서 확인할 수 있습니다. 이 문서에는 코드의 다른 영역에서 사용할 수 있는 lifespan 상태를 처리하는 방법도 포함되어 있습니다. diff --git a/docs/ko/docs/advanced/middlewares.md b/docs/ko/docs/advanced/middlewares.md index c00aedeaf..5778528a8 100644 --- a/docs/ko/docs/advanced/middlewares.md +++ b/docs/ko/docs/advanced/middlewares.md @@ -93,4 +93,4 @@ HTTP 호스트 헤더 공격을 방지하기 위해 모든 수신 요청에 올 유비콘의 `ProxyHeadersMiddleware`> MessagePack -사용 가능한 다른 미들웨어를 확인하려면 스타렛의 미들웨어 문서ASGI Awesome List를 참조하세요. +사용 가능한 다른 미들웨어를 확인하려면 스타렛의 미들웨어 문서ASGI Awesome List를 참조하세요. diff --git a/docs/ko/docs/advanced/response-cookies.md b/docs/ko/docs/advanced/response-cookies.md index 327f20afe..50da713fe 100644 --- a/docs/ko/docs/advanced/response-cookies.md +++ b/docs/ko/docs/advanced/response-cookies.md @@ -46,4 +46,4 @@ /// -사용 가능한 모든 매개변수와 옵션은 Starlette 문서에서 확인할 수 있습니다. +사용 가능한 모든 매개변수와 옵션은 Starlette 문서에서 확인할 수 있습니다. diff --git a/docs/ko/docs/advanced/response-headers.md b/docs/ko/docs/advanced/response-headers.md index e8abe0be2..e4e022c9b 100644 --- a/docs/ko/docs/advanced/response-headers.md +++ b/docs/ko/docs/advanced/response-headers.md @@ -38,4 +38,4 @@ ‘X-’ 접두어를 사용하여 커스텀 사설 헤더를 추가할 수 있습니다. -하지만, 여러분이 브라우저에서 클라이언트가 볼 수 있기를 원하는 커스텀 헤더가 있는 경우, CORS 설정에 이를 추가해야 합니다([CORS (Cross-Origin Resource Sharing)](../tutorial/cors.md){.internal-link target=_blank}에서 자세히 알아보세요). `expose_headers` 매개변수를 사용하여 Starlette의 CORS 설명서에 문서화된 대로 설정할 수 있습니다. +하지만, 여러분이 브라우저에서 클라이언트가 볼 수 있기를 원하는 커스텀 헤더가 있는 경우, CORS 설정에 이를 추가해야 합니다([CORS (Cross-Origin Resource Sharing)](../tutorial/cors.md){.internal-link target=_blank}에서 자세히 알아보세요). `expose_headers` 매개변수를 사용하여 Starlette의 CORS 설명서에 문서화된 대로 설정할 수 있습니다. diff --git a/docs/ko/docs/advanced/templates.md b/docs/ko/docs/advanced/templates.md index 4cb4cbe0d..612635713 100644 --- a/docs/ko/docs/advanced/templates.md +++ b/docs/ko/docs/advanced/templates.md @@ -124,4 +124,4 @@ Item ID: 42 ## 더 많은 세부 사항 -템플릿 테스트를 포함한 더 많은 세부 사항은 Starlette의 템플릿 문서를 확인하세요. +템플릿 테스트를 포함한 더 많은 세부 사항은 Starlette의 템플릿 문서를 확인하세요. diff --git a/docs/ko/docs/advanced/testing-websockets.md b/docs/ko/docs/advanced/testing-websockets.md index 9f3b4a451..9b6782429 100644 --- a/docs/ko/docs/advanced/testing-websockets.md +++ b/docs/ko/docs/advanced/testing-websockets.md @@ -8,6 +8,6 @@ /// note | 참고 -자세한 내용은 Starlette의 WebSocket 테스트에 관한 설명서를 참고하시길 바랍니다. +자세한 내용은 Starlette의 WebSocket 테스트에 관한 설명서를 참고하시길 바랍니다. /// diff --git a/docs/ko/docs/advanced/using-request-directly.md b/docs/ko/docs/advanced/using-request-directly.md index bfa4fa4db..b88a83bf4 100644 --- a/docs/ko/docs/advanced/using-request-directly.md +++ b/docs/ko/docs/advanced/using-request-directly.md @@ -15,7 +15,7 @@ ## `Request` 객체에 대한 세부 사항 -**FastAPI**는 실제로 내부에 **Starlette**을 사용하며, 그 위에 여러 도구를 덧붙인 구조입니다. 따라서 여러분이 필요할 때 Starlette의 `Request` 객체를 직접 사용할 수 있습니다. +**FastAPI**는 실제로 내부에 **Starlette**을 사용하며, 그 위에 여러 도구를 덧붙인 구조입니다. 따라서 여러분이 필요할 때 Starlette의 `Request` 객체를 직접 사용할 수 있습니다. `Request` 객체에서 데이터를 직접 가져오는 경우(예: 본문을 읽기)에는 FastAPI가 해당 데이터를 검증하거나 변환하지 않으며, 문서화(OpenAPI를 통한 문서 자동화(로 생성된) API 사용자 인터페이스)도 되지 않습니다. @@ -45,7 +45,7 @@ ## `Request` 설명서 -여러분은 `Request` 객체에 대한 더 자세한 내용을 공식 Starlette 설명서 사이트에서 읽어볼 수 있습니다. +여러분은 `Request` 객체에 대한 더 자세한 내용을 공식 Starlette 설명서 사이트에서 읽어볼 수 있습니다. /// note | 기술 세부사항 diff --git a/docs/ko/docs/advanced/websockets.md b/docs/ko/docs/advanced/websockets.md index fa60a428b..d9d0dd95c 100644 --- a/docs/ko/docs/advanced/websockets.md +++ b/docs/ko/docs/advanced/websockets.md @@ -182,5 +182,5 @@ FastAPI와 쉽게 통합할 수 있으면서 더 견고하고 Redis, PostgreSQL 다음 옵션에 대한 자세한 내용을 보려면 Starlette의 문서를 확인하세요: -* `WebSocket` 클래스. -* 클래스 기반 WebSocket 처리. +* `WebSocket` 클래스. +* 클래스 기반 WebSocket 처리. diff --git a/docs/ko/docs/fastapi-cli.md b/docs/ko/docs/fastapi-cli.md index 3a976af36..a1160c71f 100644 --- a/docs/ko/docs/fastapi-cli.md +++ b/docs/ko/docs/fastapi-cli.md @@ -60,7 +60,7 @@ FastAPI CLI는 Python 프로그램의 경로(예: `main.py`)를 인수로 받아 프로덕션 환경에서는 `fastapi run` 명령어를 사용합니다. 🚀 -내부적으로, **FastAPI CLI**는 고성능의, 프로덕션에 적합한, ASGI 서버인 Uvicorn을 사용합니다. 😎 +내부적으로, **FastAPI CLI**는 고성능의, 프로덕션에 적합한, ASGI 서버인 Uvicorn을 사용합니다. 😎 ## `fastapi dev` diff --git a/docs/ko/docs/features.md b/docs/ko/docs/features.md index 5e880c298..dfbf47999 100644 --- a/docs/ko/docs/features.md +++ b/docs/ko/docs/features.md @@ -159,7 +159,7 @@ FastAPI는 사용하기 매우 간편하지만, 엄청난 하여 추가할 수 있습니다. -그러나 만약 클라이언트의 브라우저에서 볼 수 있는 사용자 정의 헤더를 가지고 있다면, 그것들을 CORS 설정([CORS (Cross-Origin Resource Sharing)](cors.md){.internal-link target=_blank})에 Starlette CORS 문서에 명시된 `expose_headers` 매개변수를 이용하여 헤더들을 추가하여야합니다. +그러나 만약 클라이언트의 브라우저에서 볼 수 있는 사용자 정의 헤더를 가지고 있다면, 그것들을 CORS 설정([CORS (Cross-Origin Resource Sharing)](cors.md){.internal-link target=_blank})에 Starlette CORS 문서에 명시된 `expose_headers` 매개변수를 이용하여 헤더들을 추가하여야합니다. /// diff --git a/docs/ko/docs/tutorial/static-files.md b/docs/ko/docs/tutorial/static-files.md index 9db5e1c67..4f3e3ab28 100644 --- a/docs/ko/docs/tutorial/static-files.md +++ b/docs/ko/docs/tutorial/static-files.md @@ -38,4 +38,4 @@ ## 추가 정보 -자세한 내용과 선택 사항을 보려면 Starlette의 정적 파일에 관한 문서를 확인하십시오. +자세한 내용과 선택 사항을 보려면 Starlette의 정적 파일에 관한 문서를 확인하십시오. diff --git a/docs/ko/docs/tutorial/testing.md b/docs/ko/docs/tutorial/testing.md index a483cbf00..915ff6d22 100644 --- a/docs/ko/docs/tutorial/testing.md +++ b/docs/ko/docs/tutorial/testing.md @@ -1,6 +1,6 @@ # 테스팅 -Starlette 덕분에 **FastAPI** 를 테스트하는 일은 쉽고 즐거운 일이 되었습니다. +Starlette 덕분에 **FastAPI** 를 테스트하는 일은 쉽고 즐거운 일이 되었습니다. Starlette는 HTTPX를 기반으로 하며, 이는 Requests를 기반으로 설계되었기 때문에 매우 친숙하고 직관적입니다. diff --git a/docs/missing-translation.md b/docs/missing-translation.md index c2882e90e..bfff84766 100644 --- a/docs/missing-translation.md +++ b/docs/missing-translation.md @@ -1,7 +1,9 @@ /// warning -The current page still doesn't have a translation for this language. +This page hasn’t been translated into your language yet. 🌍 -But you can help translating it: [Contributing](https://fastapi.tiangolo.com/contributing/){.internal-link target=_blank}. +We’re currently switching to an automated translation system 🤖, which will help keep all translations complete and up to date. + +Learn more: [Contributing – Translations](https://fastapi.tiangolo.com/contributing/#translations){.internal-link target=_blank} /// diff --git a/docs/pt/docs/advanced/events.md b/docs/pt/docs/advanced/events.md index 504b6db57..2d38e0899 100644 --- a/docs/pt/docs/advanced/events.md +++ b/docs/pt/docs/advanced/events.md @@ -155,7 +155,7 @@ Por baixo, na especificação técnica ASGI, essa é a parte do Documentação do Lifespan Starlette. +Você pode ler mais sobre o manipulador `lifespan` do Starlette na Documentação do Lifespan Starlette. Incluindo como manipular estado do lifespan que pode ser usado em outras áreas do seu código. diff --git a/docs/pt/docs/advanced/middleware.md b/docs/pt/docs/advanced/middleware.md index 8167f7d27..7700939f0 100644 --- a/docs/pt/docs/advanced/middleware.md +++ b/docs/pt/docs/advanced/middleware.md @@ -93,4 +93,4 @@ Por exemplo: * Uvicorn's `ProxyHeadersMiddleware` * MessagePack -Para checar outros middlewares disponíveis, confira Documentação de Middlewares do Starlette e a Lista Incrível do ASGI. +Para checar outros middlewares disponíveis, confira Documentação de Middlewares do Starlette e a Lista Incrível do ASGI. diff --git a/docs/pt/docs/advanced/response-cookies.md b/docs/pt/docs/advanced/response-cookies.md index eed69f222..f005f0b9b 100644 --- a/docs/pt/docs/advanced/response-cookies.md +++ b/docs/pt/docs/advanced/response-cookies.md @@ -48,4 +48,4 @@ E como o `Response` pode ser usado frequentemente para definir cabeçalhos e coo /// -Para ver todos os parâmetros e opções disponíveis, verifique a documentação no Starlette. +Para ver todos os parâmetros e opções disponíveis, verifique a documentação no Starlette. diff --git a/docs/pt/docs/advanced/response-headers.md b/docs/pt/docs/advanced/response-headers.md index a8034a7a4..a1fc84cc0 100644 --- a/docs/pt/docs/advanced/response-headers.md +++ b/docs/pt/docs/advanced/response-headers.md @@ -38,4 +38,4 @@ E como a `Response` pode ser usada frequentemente para definir cabeçalhos e coo Tenha em mente que cabeçalhos personalizados proprietários podem ser adicionados usando o prefixo 'X-'. -Porém, se voce tiver cabeçalhos personalizados que deseja que um cliente no navegador possa ver, você precisa adicioná-los às suas configurações de CORS (saiba mais em [CORS (Cross-Origin Resource Sharing)](../tutorial/cors.md){.internal-link target=_blank}), usando o parâmetro `expose_headers` descrito na documentação de CORS do Starlette. +Porém, se voce tiver cabeçalhos personalizados que deseja que um cliente no navegador possa ver, você precisa adicioná-los às suas configurações de CORS (saiba mais em [CORS (Cross-Origin Resource Sharing)](../tutorial/cors.md){.internal-link target=_blank}), usando o parâmetro `expose_headers` descrito na documentação de CORS do Starlette. diff --git a/docs/pt/docs/advanced/templates.md b/docs/pt/docs/advanced/templates.md index 4d22bfbbf..65ff89fae 100644 --- a/docs/pt/docs/advanced/templates.md +++ b/docs/pt/docs/advanced/templates.md @@ -121,4 +121,4 @@ E como você está usando `StaticFiles`, este arquivo CSS será automaticamente ## Mais detalhes -Para obter mais detalhes, incluindo como testar templates, consulte a documentação da Starlette sobre templates. +Para obter mais detalhes, incluindo como testar templates, consulte a documentação da Starlette sobre templates. diff --git a/docs/pt/docs/advanced/testing-websockets.md b/docs/pt/docs/advanced/testing-websockets.md index 942771bc9..9b8193655 100644 --- a/docs/pt/docs/advanced/testing-websockets.md +++ b/docs/pt/docs/advanced/testing-websockets.md @@ -8,6 +8,6 @@ Para isso, você utiliza o `TestClient` dentro de uma instrução `with`, conect /// note | Nota -Para mais detalhes, confira a documentação do Starlette para testar WebSockets. +Para mais detalhes, confira a documentação do Starlette para testar WebSockets. /// diff --git a/docs/pt/docs/advanced/using-request-directly.md b/docs/pt/docs/advanced/using-request-directly.md index f31e2ed15..f4fb0ed8f 100644 --- a/docs/pt/docs/advanced/using-request-directly.md +++ b/docs/pt/docs/advanced/using-request-directly.md @@ -15,7 +15,7 @@ Porém há situações em que você possa precisar acessar o objeto `Request` di ## Detalhes sobre o objeto `Request` -Como o **FastAPI** é na verdade o **Starlette** por baixo, com camadas de diversas funcionalidades por cima, você pode utilizar o objeto `Request` do Starlette diretamente quando precisar. +Como o **FastAPI** é na verdade o **Starlette** por baixo, com camadas de diversas funcionalidades por cima, você pode utilizar o objeto `Request` do Starlette diretamente quando precisar. Isso significaria também que se você obtiver informações do objeto `Request` diretamente (ler o corpo da requisição por exemplo), as informações não serão validadas, convertidas ou documentadas (com o OpenAPI, para a interface de usuário automática da API) pelo FastAPI. @@ -45,7 +45,7 @@ Do mesmo jeito, você pode declarar qualquer outro parâmetro normalmente, e al ## Documentação do `Request` -Você pode ler mais sobre os detalhes do objeto `Request` no site da documentação oficial do Starlette.. +Você pode ler mais sobre os detalhes do objeto `Request` no site da documentação oficial do Starlette.. /// note | Detalhes Técnicos diff --git a/docs/pt/docs/advanced/websockets.md b/docs/pt/docs/advanced/websockets.md index 82e443886..721c0b403 100644 --- a/docs/pt/docs/advanced/websockets.md +++ b/docs/pt/docs/advanced/websockets.md @@ -182,5 +182,5 @@ Se você precisa de algo fácil de integrar com o FastAPI, mas que seja mais rob Para aprender mais sobre as opções, verifique a documentação do Starlette para: -* A classe `WebSocket`. -* Manipulação de WebSockets baseada em classes. +* A classe `WebSocket`. +* Manipulação de WebSockets baseada em classes. diff --git a/docs/pt/docs/alternatives.md b/docs/pt/docs/alternatives.md index 29c9693bb..66cf3fe12 100644 --- a/docs/pt/docs/alternatives.md +++ b/docs/pt/docs/alternatives.md @@ -419,7 +419,7 @@ Controlar toda a validação de dados, serialização de dados e modelo de docum /// -### Starlette +### Starlette Starlette é um framework/caixa de ferramentas ASGI peso leve, o que é ideal para construir serviços assíncronos de alta performance. @@ -465,7 +465,7 @@ Então, qualquer coisa que você faz com Starlette, você pode fazer diretamente /// -### Uvicorn +### Uvicorn Uvicorn é um servidor ASGI peso leve, construído com uvloop e httptools. diff --git a/docs/pt/docs/deployment/manually.md b/docs/pt/docs/deployment/manually.md index 46e580807..c7caabbcd 100644 --- a/docs/pt/docs/deployment/manually.md +++ b/docs/pt/docs/deployment/manually.md @@ -52,7 +52,7 @@ A principal coisa que você precisa para executar uma aplicação **FastAPI** (o Existem diversas alternativas, incluindo: -* Uvicorn: um servidor ASGI de alta performance. +* Uvicorn: um servidor ASGI de alta performance. * Hypercorn: um servidor ASGI compátivel com HTTP/2, Trio e outros recursos. * Daphne: servidor ASGI construído para Django Channels. * Granian: um servidor HTTP Rust para aplicações Python. diff --git a/docs/pt/docs/fastapi-cli.md b/docs/pt/docs/fastapi-cli.md index 829686631..f33c2ba2a 100644 --- a/docs/pt/docs/fastapi-cli.md +++ b/docs/pt/docs/fastapi-cli.md @@ -60,7 +60,7 @@ O FastAPI CLI recebe o caminho do seu programa Python, detecta automaticamente a Para produção você usaria `fastapi run` no lugar. 🚀 -Internamente, **FastAPI CLI** usa Uvicorn, um servidor ASGI de alta performance e pronto para produção. 😎 +Internamente, **FastAPI CLI** usa Uvicorn, um servidor ASGI de alta performance e pronto para produção. 😎 ## `fastapi dev` diff --git a/docs/pt/docs/features.md b/docs/pt/docs/features.md index a90a8094b..ccc3300d6 100644 --- a/docs/pt/docs/features.md +++ b/docs/pt/docs/features.md @@ -159,7 +159,7 @@ Qualquer integração é projetada para ser tão simples de usar (com dependênc ## Recursos do Starlette -**FastAPI** é totalmente compatível com (e baseado no) Starlette. Então, qualquer código adicional Starlette que você tiver, também funcionará. +**FastAPI** é totalmente compatível com (e baseado no) Starlette. Então, qualquer código adicional Starlette que você tiver, também funcionará. `FastAPI` é na verdade uma sub-classe do `Starlette`. Então, se você já conhece ou usa Starlette, a maioria das funcionalidades se comportará da mesma forma. diff --git a/docs/pt/docs/history-design-future.md b/docs/pt/docs/history-design-future.md index 4ec217405..1d0768c62 100644 --- a/docs/pt/docs/history-design-future.md +++ b/docs/pt/docs/history-design-future.md @@ -58,7 +58,7 @@ Após testar várias alternativas, eu decidi que usaria o **Starlette**, outro requisito chave. +Durante o desenvolvimento, eu também contribuí com o **Starlette**, outro requisito chave. ## Desenvolvimento diff --git a/docs/pt/docs/how-to/custom-request-and-route.md b/docs/pt/docs/how-to/custom-request-and-route.md index 8f432f6fe..151a0f5d4 100644 --- a/docs/pt/docs/how-to/custom-request-and-route.md +++ b/docs/pt/docs/how-to/custom-request-and-route.md @@ -66,7 +66,7 @@ O dicionário `scope` e a função `receive` são ambos parte da especificação E essas duas coisas, `scope` e `receive`, são o que é necessário para criar uma nova instância de `Request`. -Para aprender mais sobre o `Request` confira a documentação do Starlette sobre Requests. +Para aprender mais sobre o `Request` confira a documentação do Starlette sobre Requests. /// diff --git a/docs/pt/docs/index.md b/docs/pt/docs/index.md index ce9929bf4..a361913c3 100644 --- a/docs/pt/docs/index.md +++ b/docs/pt/docs/index.md @@ -123,7 +123,7 @@ Se você estiver construindo uma aplicação Starlette para as partes web. +* Starlette para as partes web. * Pydantic para a parte de dados. ## Instalação @@ -229,7 +229,7 @@ INFO: Application startup complete.
Sobre o comando fastapi dev main.py... -O comando `fastapi dev` lê o seu arquivo `main.py`, identifica o aplicativo **FastAPI** nele, e inicia um servidor usando o Uvicorn. +O comando `fastapi dev` lê o seu arquivo `main.py`, identifica o aplicativo **FastAPI** nele, e inicia um servidor usando o Uvicorn. Por padrão, o `fastapi dev` iniciará com *auto-reload* habilitado para desenvolvimento local. @@ -471,7 +471,7 @@ Utilizado pelo Starlette: Utilizado pelo FastAPI / Starlette: -* uvicorn - para o servidor que carrega e serve a sua aplicação. Isto inclui `uvicorn[standard]`, que inclui algumas dependências (e.g. `uvloop`) necessárias para servir em alta performance. +* uvicorn - para o servidor que carrega e serve a sua aplicação. Isto inclui `uvicorn[standard]`, que inclui algumas dependências (e.g. `uvloop`) necessárias para servir em alta performance. * `fastapi-cli` - que disponibiliza o comando `fastapi`. ### Sem as dependências `standard` diff --git a/docs/pt/docs/tutorial/background-tasks.md b/docs/pt/docs/tutorial/background-tasks.md index 0f3796371..b8ab58cda 100644 --- a/docs/pt/docs/tutorial/background-tasks.md +++ b/docs/pt/docs/tutorial/background-tasks.md @@ -61,7 +61,7 @@ E então outra tarefa em segundo plano gerada na _função de operação de cami ## Detalhes técnicos -A classe `BackgroundTasks` vem diretamente de `starlette.background`. +A classe `BackgroundTasks` vem diretamente de `starlette.background`. Ela é importada/incluída diretamente no FastAPI para que você possa importá-la do `fastapi` e evitar a importação acidental da alternativa `BackgroundTask` (sem o `s` no final) de `starlette.background`. @@ -69,7 +69,7 @@ Usando apenas `BackgroundTasks` (e não `BackgroundTask`), é então possível u Ainda é possível usar `BackgroundTask` sozinho no FastAPI, mas você deve criar o objeto em seu código e retornar uma Starlette `Response` incluindo-o. -Você pode ver mais detalhes na documentação oficiais da Starlette para tarefas em segundo plano . +Você pode ver mais detalhes na documentação oficiais da Starlette para tarefas em segundo plano . ## Ressalva diff --git a/docs/pt/docs/tutorial/first-steps.md b/docs/pt/docs/tutorial/first-steps.md index 5184d2d5f..e696bbbb7 100644 --- a/docs/pt/docs/tutorial/first-steps.md +++ b/docs/pt/docs/tutorial/first-steps.md @@ -155,7 +155,7 @@ Você também pode usá-lo para gerar código automaticamente para clientes que `FastAPI` é uma classe que herda diretamente de `Starlette`. -Você pode usar todas as funcionalidades do Starlette com `FastAPI` também. +Você pode usar todas as funcionalidades do Starlette com `FastAPI` também. /// diff --git a/docs/pt/docs/tutorial/handling-errors.md b/docs/pt/docs/tutorial/handling-errors.md index 098195db7..5cb92c744 100644 --- a/docs/pt/docs/tutorial/handling-errors.md +++ b/docs/pt/docs/tutorial/handling-errors.md @@ -83,7 +83,7 @@ Mas caso você precise, para um cenário mais complexo, você pode adicionar hea ## Instalando manipuladores de exceções customizados -Você pode adicionar manipuladores de exceção customizados com a mesma seção de utilidade de exceções presentes no Starlette +Você pode adicionar manipuladores de exceção customizados com a mesma seção de utilidade de exceções presentes no Starlette Digamos que você tenha uma exceção customizada `UnicornException` que você (ou uma biblioteca que você use) precise lançar (`raise`). diff --git a/docs/pt/docs/tutorial/middleware.md b/docs/pt/docs/tutorial/middleware.md index 32b81c646..0f5009b6d 100644 --- a/docs/pt/docs/tutorial/middleware.md +++ b/docs/pt/docs/tutorial/middleware.md @@ -37,7 +37,7 @@ A função middleware recebe: Tenha em mente que cabeçalhos proprietários personalizados podem ser adicionados usando o prefixo 'X-'. -Mas se você tiver cabeçalhos personalizados desejando que um cliente em um navegador esteja apto a ver, você precisa adicioná-los às suas configurações CORS ([CORS (Cross-Origin Resource Sharing)](cors.md){.internal-link target=_blank}) usando o parâmetro `expose_headers` documentado em Documentos CORS da Starlette. +Mas se você tiver cabeçalhos personalizados desejando que um cliente em um navegador esteja apto a ver, você precisa adicioná-los às suas configurações CORS ([CORS (Cross-Origin Resource Sharing)](cors.md){.internal-link target=_blank}) usando o parâmetro `expose_headers` documentado em Documentos CORS da Starlette. /// diff --git a/docs/pt/docs/tutorial/static-files.md b/docs/pt/docs/tutorial/static-files.md index 0660078f4..30e1af8e6 100644 --- a/docs/pt/docs/tutorial/static-files.md +++ b/docs/pt/docs/tutorial/static-files.md @@ -37,4 +37,4 @@ Todos esses parâmetros podem ser diferentes de "`static`", ajuste-os de acordo ## Mais informações -Para mais detalhes e opções, verifique Starlette's docs about Static Files. +Para mais detalhes e opções, verifique Starlette's docs about Static Files. diff --git a/docs/pt/docs/tutorial/testing.md b/docs/pt/docs/tutorial/testing.md index 8eb2f29b7..dc505105a 100644 --- a/docs/pt/docs/tutorial/testing.md +++ b/docs/pt/docs/tutorial/testing.md @@ -1,6 +1,6 @@ # Testando -Graças ao Starlette, testar aplicativos **FastAPI** é fácil e agradável. +Graças ao Starlette, testar aplicativos **FastAPI** é fácil e agradável. Ele é baseado no HTTPX, que por sua vez é projetado com base em Requests, por isso é muito familiar e intuitivo. diff --git a/docs/ru/docs/advanced/events.md b/docs/ru/docs/advanced/events.md index 6e1b49035..20d1df98a 100644 --- a/docs/ru/docs/advanced/events.md +++ b/docs/ru/docs/advanced/events.md @@ -154,7 +154,7 @@ async with lifespan(app): /// info | Информация -Вы можете прочитать больше про обработчики `lifespan` в Starlette в документации Starlette по Lifespan. +Вы можете прочитать больше про обработчики `lifespan` в Starlette в документации Starlette по Lifespan. Включая то, как работать с состоянием lifespan, которое можно использовать в других частях вашего кода. diff --git a/docs/ru/docs/advanced/middleware.md b/docs/ru/docs/advanced/middleware.md index 28802fd57..82c86b231 100644 --- a/docs/ru/docs/advanced/middleware.md +++ b/docs/ru/docs/advanced/middleware.md @@ -94,4 +94,4 @@ app.add_middleware(UnicornMiddleware, some_config="rainbow") - `ProxyHeadersMiddleware` от Uvicorn - MessagePack -Чтобы увидеть другие доступные middleware, посмотрите документацию по middleware в Starlette и список ASGI Awesome. +Чтобы увидеть другие доступные middleware, посмотрите документацию по middleware в Starlette и список ASGI Awesome. diff --git a/docs/ru/docs/advanced/response-cookies.md b/docs/ru/docs/advanced/response-cookies.md index 3aa32b9bb..9319aba6e 100644 --- a/docs/ru/docs/advanced/response-cookies.md +++ b/docs/ru/docs/advanced/response-cookies.md @@ -48,4 +48,4 @@ /// -Чтобы увидеть все доступные параметры и настройки, ознакомьтесь с документацией Starlette. +Чтобы увидеть все доступные параметры и настройки, ознакомьтесь с документацией Starlette. diff --git a/docs/ru/docs/advanced/response-headers.md b/docs/ru/docs/advanced/response-headers.md index 81e52cb69..1c9360b31 100644 --- a/docs/ru/docs/advanced/response-headers.md +++ b/docs/ru/docs/advanced/response-headers.md @@ -38,4 +38,4 @@ Помните, что собственные проприетарные заголовки можно добавлять, используя префикс `X-`. -Но если у вас есть пользовательские заголовки, которые вы хотите показывать клиенту в браузере, вам нужно добавить их в настройки CORS (подробнее см. в [CORS (Cross-Origin Resource Sharing)](../tutorial/cors.md){.internal-link target=_blank}), используя параметр `expose_headers`, описанный в документации Starlette по CORS. +Но если у вас есть пользовательские заголовки, которые вы хотите показывать клиенту в браузере, вам нужно добавить их в настройки CORS (подробнее см. в [CORS (Cross-Origin Resource Sharing)](../tutorial/cors.md){.internal-link target=_blank}), используя параметр `expose_headers`, описанный в документации Starlette по CORS. diff --git a/docs/ru/docs/advanced/templates.md b/docs/ru/docs/advanced/templates.md index 5675ff48a..204e88760 100644 --- a/docs/ru/docs/advanced/templates.md +++ b/docs/ru/docs/advanced/templates.md @@ -123,4 +123,4 @@ Item ID: 42 ## Подробнее { #more-details } -Больше подробностей, включая то, как тестировать шаблоны, смотрите в документации Starlette по шаблонам. +Больше подробностей, включая то, как тестировать шаблоны, смотрите в документации Starlette по шаблонам. diff --git a/docs/ru/docs/advanced/testing-events.md b/docs/ru/docs/advanced/testing-events.md index 1bf8e4723..e0ec77439 100644 --- a/docs/ru/docs/advanced/testing-events.md +++ b/docs/ru/docs/advanced/testing-events.md @@ -5,7 +5,7 @@ {* ../../docs_src/app_testing/tutorial004.py hl[9:15,18,27:28,30:32,41:43] *} -Вы можете узнать больше подробностей в статье [Запуск lifespan в тестах на официальном сайте документации Starlette.](https://www.starlette.io/lifespan/#running-lifespan-in-tests) +Вы можете узнать больше подробностей в статье [Запуск lifespan в тестах на официальном сайте документации Starlette.](https://www.starlette.dev/lifespan/#running-lifespan-in-tests) Для устаревших событий `startup` и `shutdown` вы можете использовать `TestClient` следующим образом: diff --git a/docs/ru/docs/advanced/testing-websockets.md b/docs/ru/docs/advanced/testing-websockets.md index 7c0ca2594..e840a03f2 100644 --- a/docs/ru/docs/advanced/testing-websockets.md +++ b/docs/ru/docs/advanced/testing-websockets.md @@ -8,6 +8,6 @@ /// note | Примечание -Подробности смотрите в документации Starlette по тестированию WebSocket. +Подробности смотрите в документации Starlette по тестированию WebSocket. /// diff --git a/docs/ru/docs/advanced/using-request-directly.md b/docs/ru/docs/advanced/using-request-directly.md index bff2ddcb7..b92221610 100644 --- a/docs/ru/docs/advanced/using-request-directly.md +++ b/docs/ru/docs/advanced/using-request-directly.md @@ -15,7 +15,7 @@ ## Подробности об объекте `Request` { #details-about-the-request-object } -Так как под капотом **FastAPI** — это **Starlette** с дополнительным слоем инструментов, вы можете при необходимости напрямую использовать объект `Request` из Starlette. +Так как под капотом **FastAPI** — это **Starlette** с дополнительным слоем инструментов, вы можете при необходимости напрямую использовать объект `Request` из Starlette. Это также означает, что если вы получаете данные напрямую из объекта `Request` (например, читаете тело запроса), то они не будут валидироваться, конвертироваться или документироваться (с OpenAPI, для автоматического пользовательского интерфейса API) средствами FastAPI. @@ -45,7 +45,7 @@ ## Документация по `Request` { #request-documentation } -Подробнее об объекте `Request` на официальном сайте документации Starlette. +Подробнее об объекте `Request` на официальном сайте документации Starlette. /// note | Технические детали diff --git a/docs/ru/docs/advanced/websockets.md b/docs/ru/docs/advanced/websockets.md index b73fa1ddb..f26185bea 100644 --- a/docs/ru/docs/advanced/websockets.md +++ b/docs/ru/docs/advanced/websockets.md @@ -182,5 +182,5 @@ Client #1596980209979 left the chat Для более глубокого изучения темы воспользуйтесь документацией Starlette: -* The `WebSocket` class. -* Class-based WebSocket handling. +* The `WebSocket` class. +* Class-based WebSocket handling. diff --git a/docs/ru/docs/alternatives.md b/docs/ru/docs/alternatives.md index 6380bcc45..17b54aad2 100644 --- a/docs/ru/docs/alternatives.md +++ b/docs/ru/docs/alternatives.md @@ -417,7 +417,7 @@ Pydantic — это библиотека для определения вали /// -### Starlette { #starlette } +### Starlette { #starlette } Starlette — это лёгкий ASGI фреймворк/набор инструментов, идеально подходящий для создания высокопроизводительных asyncio‑сервисов. @@ -462,7 +462,7 @@ ASGI — это новый «стандарт», разрабатываемый /// -### Uvicorn { #uvicorn } +### Uvicorn { #uvicorn } Uvicorn — молниеносный ASGI-сервер, построенный на uvloop и httptools. diff --git a/docs/ru/docs/deployment/manually.md b/docs/ru/docs/deployment/manually.md index 37fed5780..93287372a 100644 --- a/docs/ru/docs/deployment/manually.md +++ b/docs/ru/docs/deployment/manually.md @@ -52,7 +52,7 @@ FastAPI использует стандарт для построения Python Есть несколько альтернатив, например: -* Uvicorn: высокопроизводительный ASGI‑сервер. +* Uvicorn: высокопроизводительный ASGI‑сервер. * Hypercorn: ASGI‑сервер, среди прочего совместимый с HTTP/2 и Trio. * Daphne: ASGI‑сервер, созданный для Django Channels. * Granian: HTTP‑сервер на Rust для Python‑приложений. diff --git a/docs/ru/docs/fastapi-cli.md b/docs/ru/docs/fastapi-cli.md index 156e3d200..72cf55e7b 100644 --- a/docs/ru/docs/fastapi-cli.md +++ b/docs/ru/docs/fastapi-cli.md @@ -52,7 +52,7 @@ FastAPI CLI берет путь к вашей Python-программе (нап Для работы в режиме продакшн вместо `fastapi dev` нужно использовать `fastapi run`. 🚀 -Внутри **FastAPI CLI** используется Uvicorn, высокопроизводительный, готовый к работе в продакшне ASGI-сервер. 😎 +Внутри **FastAPI CLI** используется Uvicorn, высокопроизводительный, готовый к работе в продакшне ASGI-сервер. 😎 ## `fastapi dev` { #fastapi-dev } diff --git a/docs/ru/docs/features.md b/docs/ru/docs/features.md index 91ffe331b..703ff951e 100644 --- a/docs/ru/docs/features.md +++ b/docs/ru/docs/features.md @@ -159,7 +159,7 @@ FastAPI включает в себя чрезвычайно простую в и ## Возможности Starlette { #starlette-features } -**FastAPI** основан на Starlette и полностью совместим с ним. Так что любой дополнительный код Starlette, который у вас есть, также будет работать. +**FastAPI** основан на Starlette и полностью совместим с ним. Так что любой дополнительный код Starlette, который у вас есть, также будет работать. На самом деле, `FastAPI` — это подкласс `Starlette`. Таким образом, если вы уже знаете или используете Starlette, большая часть функционала будет работать так же. diff --git a/docs/ru/docs/history-design-future.md b/docs/ru/docs/history-design-future.md index d679af3e3..9cdd53376 100644 --- a/docs/ru/docs/history-design-future.md +++ b/docs/ru/docs/history-design-future.md @@ -58,7 +58,7 @@ По моим предложениям был изменён код этого фреймворка, чтобы сделать его полностью совместимым с JSON Schema, поддержать различные способы определения ограничений и улучшить поддержку в редакторах кода (проверки типов, автозавершение) на основе тестов в нескольких редакторах. -В то же время, я принимал участие в разработке **Starlette**, ещё один из основных компонентов FastAPI. +В то же время, я принимал участие в разработке **Starlette**, ещё один из основных компонентов FastAPI. ## Разработка { #development } diff --git a/docs/ru/docs/how-to/custom-request-and-route.md b/docs/ru/docs/how-to/custom-request-and-route.md index df8a5ee3c..1b8d7f7ed 100644 --- a/docs/ru/docs/how-to/custom-request-and-route.md +++ b/docs/ru/docs/how-to/custom-request-and-route.md @@ -66,7 +66,7 @@ Именно этих двух компонентов — `scope` и `receive` — достаточно, чтобы создать новый экземпляр `Request`. -Чтобы узнать больше о `Request`, см. документацию Starlette о запросах. +Чтобы узнать больше о `Request`, см. документацию Starlette о запросах. /// diff --git a/docs/ru/docs/index.md b/docs/ru/docs/index.md index 1fcc9ea9d..75cd63223 100644 --- a/docs/ru/docs/index.md +++ b/docs/ru/docs/index.md @@ -123,7 +123,7 @@ FastAPI — это современный, быстрый (высокопрои FastAPI стоит на плечах гигантов: -* Starlette для части, связанной с вебом. +* Starlette для части, связанной с вебом. * Pydantic для части, связанной с данными. ## Установка { #installation } @@ -229,7 +229,7 @@ INFO: Application startup complete.
О команде fastapi dev main.py... -Команда `fastapi dev` читает ваш файл `main.py`, находит в нём приложение **FastAPI** и запускает сервер с помощью Uvicorn. +Команда `fastapi dev` читает ваш файл `main.py`, находит в нём приложение **FastAPI** и запускает сервер с помощью Uvicorn. По умолчанию `fastapi dev` запускается с включённой авто-перезагрузкой для локальной разработки. @@ -470,7 +470,7 @@ FastAPI зависит от Pydantic и Starlette. Используется FastAPI: -* uvicorn — сервер, который загружает и обслуживает ваше приложение. Включает `uvicorn[standard]`, содержащий некоторые зависимости (например, `uvloop`), нужные для высокой производительности. +* uvicorn — сервер, который загружает и обслуживает ваше приложение. Включает `uvicorn[standard]`, содержащий некоторые зависимости (например, `uvloop`), нужные для высокой производительности. * `fastapi-cli[standard]` — чтобы предоставить команду `fastapi`. * Включает `fastapi-cloud-cli`, который позволяет развернуть ваше приложение FastAPI в FastAPI Cloud. diff --git a/docs/ru/docs/tutorial/background-tasks.md b/docs/ru/docs/tutorial/background-tasks.md index 9b6f0c8d3..1ed8522d6 100644 --- a/docs/ru/docs/tutorial/background-tasks.md +++ b/docs/ru/docs/tutorial/background-tasks.md @@ -61,7 +61,7 @@ ## Технические детали { #technical-details } -Класс `BackgroundTasks` приходит напрямую из `starlette.background`. +Класс `BackgroundTasks` приходит напрямую из `starlette.background`. Он импортируется/включается прямо в FastAPI, чтобы вы могли импортировать его из `fastapi` и избежать случайного импорта альтернативного `BackgroundTask` (без `s` на конце) из `starlette.background`. @@ -69,7 +69,7 @@ По‑прежнему можно использовать один `BackgroundTask` в FastAPI, но тогда вам нужно создать объект в своём коде и вернуть Starlette `Response`, включающий его. -Подробнее см. в официальной документации Starlette по фоновым задачам. +Подробнее см. в официальной документации Starlette по фоновым задачам. ## Предостережение { #caveat } diff --git a/docs/ru/docs/tutorial/first-steps.md b/docs/ru/docs/tutorial/first-steps.md index 9cdf76f5d..c82118cbe 100644 --- a/docs/ru/docs/tutorial/first-steps.md +++ b/docs/ru/docs/tutorial/first-steps.md @@ -155,7 +155,7 @@ OpenAPI определяет схему API для вашего API. И эта `FastAPI` — это класс, который напрямую наследуется от `Starlette`. -Вы можете использовать весь функционал Starlette и в `FastAPI`. +Вы можете использовать весь функционал Starlette и в `FastAPI`. /// diff --git a/docs/ru/docs/tutorial/handling-errors.md b/docs/ru/docs/tutorial/handling-errors.md index 33b7babf5..2378c8b04 100644 --- a/docs/ru/docs/tutorial/handling-errors.md +++ b/docs/ru/docs/tutorial/handling-errors.md @@ -81,7 +81,7 @@ ## Установка пользовательских обработчиков исключений { #install-custom-exception-handlers } -Вы можете добавить пользовательские обработчики исключений с помощью то же самое исключение - утилиты от Starlette. +Вы можете добавить пользовательские обработчики исключений с помощью то же самое исключение - утилиты от Starlette. Допустим, у вас есть пользовательское исключение `UnicornException`, которое вы (или используемая вами библиотека) можете `вызвать`. diff --git a/docs/ru/docs/tutorial/middleware.md b/docs/ru/docs/tutorial/middleware.md index ea535a151..5803b398b 100644 --- a/docs/ru/docs/tutorial/middleware.md +++ b/docs/ru/docs/tutorial/middleware.md @@ -39,7 +39,7 @@ Имейте в виду, что можно добавлять свои собственные заголовки при помощи префикса 'X-'. -Если же вы хотите добавить собственные заголовки, которые клиент сможет увидеть в браузере, то вам потребуется добавить их в настройки CORS ([CORS (Cross-Origin Resource Sharing)](cors.md){.internal-link target=_blank}), используя параметр `expose_headers`, см. документацию Starlette's CORS docs. +Если же вы хотите добавить собственные заголовки, которые клиент сможет увидеть в браузере, то вам потребуется добавить их в настройки CORS ([CORS (Cross-Origin Resource Sharing)](cors.md){.internal-link target=_blank}), используя параметр `expose_headers`, см. документацию Starlette's CORS docs. /// diff --git a/docs/ru/docs/tutorial/static-files.md b/docs/ru/docs/tutorial/static-files.md index 282c84db1..8455aea0a 100644 --- a/docs/ru/docs/tutorial/static-files.md +++ b/docs/ru/docs/tutorial/static-files.md @@ -38,4 +38,4 @@ OpenAPI и документация из вашего главного прил ## Больше информации { #more-info } -Для получения дополнительной информации о деталях и настройках ознакомьтесь с Документацией Starlette о статических файлах. +Для получения дополнительной информации о деталях и настройках ознакомьтесь с Документацией Starlette о статических файлах. diff --git a/docs/ru/docs/tutorial/testing.md b/docs/ru/docs/tutorial/testing.md index 94e9ae8ae..0224798b1 100644 --- a/docs/ru/docs/tutorial/testing.md +++ b/docs/ru/docs/tutorial/testing.md @@ -1,6 +1,6 @@ # Тестирование { #testing } -Благодаря Starlette, тестировать приложения **FastAPI** легко и приятно. +Благодаря Starlette, тестировать приложения **FastAPI** легко и приятно. Тестирование основано на библиотеке HTTPX, которая в свою очередь основана на библиотеке Requests, так что все действия знакомы и интуитивно понятны. diff --git a/docs/tr/docs/advanced/testing-websockets.md b/docs/tr/docs/advanced/testing-websockets.md index ddacca449..effe557d1 100644 --- a/docs/tr/docs/advanced/testing-websockets.md +++ b/docs/tr/docs/advanced/testing-websockets.md @@ -8,6 +8,6 @@ Bu işlem için, `TestClient`'ı bir `with` ifadesinde kullanarak WebSocket'e ba /// note | Not -Daha fazla detay için Starlette'in Websockets'i Test Etmek dokümantasyonunu inceleyin. +Daha fazla detay için Starlette'in Websockets'i Test Etmek dokümantasyonunu inceleyin. /// diff --git a/docs/tr/docs/alternatives.md b/docs/tr/docs/alternatives.md index c98b966b5..9b603ea81 100644 --- a/docs/tr/docs/alternatives.md +++ b/docs/tr/docs/alternatives.md @@ -415,7 +415,7 @@ Bütün veri doğrulama, veri dönüştürme ve JSON Şemasına bağlı otomatik /// -### Starlette +### Starlette Starlette hafif bir ASGI framework'ü ve yüksek performanslı asyncio servisleri oluşturmak için ideal. @@ -460,7 +460,7 @@ Yani, Starlette ile yapabileceğiniz her şeyi, Starlette'in bir nevi güçlendi /// -### Uvicorn +### Uvicorn Uvicorn, uvlook ile httptools üzerine kurulu ışık hzında bir ASGI sunucusudur. diff --git a/docs/tr/docs/features.md b/docs/tr/docs/features.md index 5d40b1086..86085c5e9 100644 --- a/docs/tr/docs/features.md +++ b/docs/tr/docs/features.md @@ -166,7 +166,7 @@ Bütün entegrasyonlar kullanımı kolay olmak üzere (zorunluluklar ile beraber ## Starlette özellikleri -**FastAPI**, Starlette ile tamamiyle uyumlu ve üzerine kurulu. Yani FastAPI üzerine ekleme yapacağınız herhangi bir Starlette kodu da çalışacaktır. +**FastAPI**, Starlette ile tamamiyle uyumlu ve üzerine kurulu. Yani FastAPI üzerine ekleme yapacağınız herhangi bir Starlette kodu da çalışacaktır. `FastAPI` aslında `Starlette`'nin bir sub-class'ı. Eğer Starlette'nin nasıl kullanılacağını biliyor isen, çoğu işlevini aynı şekilde yapıyor. diff --git a/docs/tr/docs/history-design-future.md b/docs/tr/docs/history-design-future.md index 8b2662bc3..cad290828 100644 --- a/docs/tr/docs/history-design-future.md +++ b/docs/tr/docs/history-design-future.md @@ -58,7 +58,7 @@ Hepsi, tüm geliştiriciler için en iyi geliştirme deneyimini sağlayacak şek Sonra, JSON Schema ile tamamen uyumlu olmasını sağlamak, kısıtlama bildirimlerini tanımlamanın farklı yollarını desteklemek ve birkaç editördeki testlere dayanarak editör desteğini (tip kontrolleri, otomatik tamamlama) geliştirmek için katkıda bulundum. -Geliştirme sırasında, diğer ana gereksinim olan **Starlette**'e de katkıda bulundum. +Geliştirme sırasında, diğer ana gereksinim olan **Starlette**'e de katkıda bulundum. ## Geliştirme diff --git a/docs/tr/docs/index.md b/docs/tr/docs/index.md index c7a2b2fbd..516d5959e 100644 --- a/docs/tr/docs/index.md +++ b/docs/tr/docs/index.md @@ -123,7 +123,7 @@ Eğer API yerine, terminalde kullanılmak üzere bir Starlette. +* Web tarafı için Starlette. * Data tarafı için Pydantic. ## Kurulum @@ -138,7 +138,7 @@ $ pip install fastapi
-Uygulamamızı kullanılabilir hale getirmek için Uvicorn ya da Hypercorn gibi bir ASGI sunucusuna ihtiyacımız olacak. +Uygulamamızı kullanılabilir hale getirmek için Uvicorn ya da Hypercorn gibi bir ASGI sunucusuna ihtiyacımız olacak.
@@ -463,7 +463,7 @@ Starlette tarafında kullanılan: Hem FastAPI hem de Starlette tarafından kullanılan: -* uvicorn - oluşturduğumuz uygulamayı servis edecek web sunucusu görevini üstlenir. +* uvicorn - oluşturduğumuz uygulamayı servis edecek web sunucusu görevini üstlenir. * orjson - `ORJSONResponse` kullanacaksanız gereklidir. * ujson - `UJSONResponse` kullanacaksanız gerekli. diff --git a/docs/tr/docs/tutorial/first-steps.md b/docs/tr/docs/tutorial/first-steps.md index 2d2949b50..9a8ef762d 100644 --- a/docs/tr/docs/tutorial/first-steps.md +++ b/docs/tr/docs/tutorial/first-steps.md @@ -139,7 +139,7 @@ Ayrıca, API'ınızla iletişim kuracak önyüz, mobil veya IoT uygulamaları gi `FastAPI` doğrudan `Starlette`'i miras alan bir sınıftır. -Starlette'in tüm işlevselliğini `FastAPI` ile de kullanabilirsiniz. +Starlette'in tüm işlevselliğini `FastAPI` ile de kullanabilirsiniz. /// diff --git a/docs/tr/docs/tutorial/static-files.md b/docs/tr/docs/tutorial/static-files.md index db30f13bc..4542aca77 100644 --- a/docs/tr/docs/tutorial/static-files.md +++ b/docs/tr/docs/tutorial/static-files.md @@ -37,4 +37,4 @@ Bu parametrelerin hepsi "`static`"den farklı olabilir, bunları kendi uygulaman ## Daha Fazla Bilgi -Daha fazla detay ve seçenek için Starlette'in Statik Dosyalar hakkındaki dokümantasyonunu incelleyin. +Daha fazla detay ve seçenek için Starlette'in Statik Dosyalar hakkındaki dokümantasyonunu incelleyin. diff --git a/docs/uk/docs/alternatives.md b/docs/uk/docs/alternatives.md index 1acbe237a..786df45c5 100644 --- a/docs/uk/docs/alternatives.md +++ b/docs/uk/docs/alternatives.md @@ -415,7 +415,7 @@ Pydantic — це бібліотека для визначення переві /// -### Starlette +### Starlette Starlette — це легкий фреймворк/набір інструментів ASGI, який ідеально підходить для створення високопродуктивних asyncio сервісів. @@ -460,7 +460,7 @@ ASGI — це новий «стандарт», який розробляєтьс /// -### Uvicorn +### Uvicorn Uvicorn — це блискавичний сервер ASGI, побудований на uvloop і httptools. diff --git a/docs/uk/docs/fastapi-cli.md b/docs/uk/docs/fastapi-cli.md index 6bbbbc326..f18b10471 100644 --- a/docs/uk/docs/fastapi-cli.md +++ b/docs/uk/docs/fastapi-cli.md @@ -60,7 +60,7 @@ FastAPI CLI приймає шлях до Вашої Python програми (н Натомість, для запуску у продакшн використовуйте `fastapi run`. 🚀 -Всередині **FastAPI CLI** використовує Uvicorn, високопродуктивний, production-ready, ASGI cервер. 😎 +Всередині **FastAPI CLI** використовує Uvicorn, високопродуктивний, production-ready, ASGI cервер. 😎 ## `fastapi dev` diff --git a/docs/uk/docs/features.md b/docs/uk/docs/features.md index 7d679d8ee..aa0ef7c79 100644 --- a/docs/uk/docs/features.md +++ b/docs/uk/docs/features.md @@ -147,7 +147,7 @@ FastAPI має розумні налаштування **за замовчува ## Можливості Starlette -**FastAPI** повністю сумісний із (та побудований на основі) Starlette. Тому будь-який додатковий код Starlette, який ви маєте, також працюватиме. +**FastAPI** повністю сумісний із (та побудований на основі) Starlette. Тому будь-який додатковий код Starlette, який ви маєте, також працюватиме. **FastAPI** фактично є підкласом **Starlette**. Тому, якщо ви вже знайомі зі Starlette або використовуєте його, більшість функціональності працюватиме так само. diff --git a/docs/uk/docs/index.md b/docs/uk/docs/index.md index 7e919e257..0811a4c7b 100644 --- a/docs/uk/docs/index.md +++ b/docs/uk/docs/index.md @@ -112,7 +112,7 @@ FastAPI - це сучасний, швидкий (високопродуктив FastAPI стоїть на плечах гігантів: -* Starlette для web частини. +* Starlette для web частини. * Pydantic для частини даних. ## Вставновлення @@ -127,7 +127,7 @@ $ pip install fastapi
-Вам також знадобиться сервер ASGI для продакшину, наприклад Uvicorn або Hypercorn. +Вам також знадобиться сервер ASGI для продакшину, наприклад Uvicorn або Hypercorn.
@@ -452,7 +452,7 @@ Starlette використовує: FastAPI / Starlette використовують: -* uvicorn - для сервера, який завантажує та обслуговує вашу програму. +* uvicorn - для сервера, який завантажує та обслуговує вашу програму. * orjson - Необхідно, якщо Ви хочете використовувати `ORJSONResponse`. * ujson - Необхідно, якщо Ви хочете використовувати `UJSONResponse`. diff --git a/docs/uk/docs/tutorial/background-tasks.md b/docs/uk/docs/tutorial/background-tasks.md index 912ba8c2a..0a9349650 100644 --- a/docs/uk/docs/tutorial/background-tasks.md +++ b/docs/uk/docs/tutorial/background-tasks.md @@ -62,7 +62,7 @@ ## Технічні деталі -Клас `BackgroundTasks` походить безпосередньо з `starlette.background`. +Клас `BackgroundTasks` походить безпосередньо з `starlette.background`. Він імпортується безпосередньо у FastAPI, щоб Ви могли використовувати його з `fastapi` і випадково не імпортували `BackgroundTask` (без s в кінці) з `starlette.background`. @@ -70,7 +70,7 @@ Також можна використовувати `BackgroundTask` окремо в FastAPI, але для цього Вам доведеться створити об'єкт у коді та повернути Starlette `Response`, включаючи його. -Детальніше можна почитати в офіційній документації Starlette про фонові задачі . +Детальніше можна почитати в офіційній документації Starlette про фонові задачі . ## Застереження diff --git a/docs/uk/docs/tutorial/first-steps.md b/docs/uk/docs/tutorial/first-steps.md index e910c4ccc..3f861cb48 100644 --- a/docs/uk/docs/tutorial/first-steps.md +++ b/docs/uk/docs/tutorial/first-steps.md @@ -163,7 +163,7 @@ OpenAPI описує схему для вашого API. І ця схема вк `FastAPI` це клас, який успадковується безпосередньо від `Starlette`. -Ви також можете використовувати всю функціональність Starlette у `FastAPI`. +Ви також можете використовувати всю функціональність Starlette у `FastAPI`. /// diff --git a/docs/uk/docs/tutorial/handling-errors.md b/docs/uk/docs/tutorial/handling-errors.md index 12a356cd0..32de73b2a 100644 --- a/docs/uk/docs/tutorial/handling-errors.md +++ b/docs/uk/docs/tutorial/handling-errors.md @@ -81,7 +81,7 @@ ## Встановлення власних обробників помилок -Ви можете додати власні обробники помилок за допомогою тих самих утиліт обробки помилок зі Starlette. +Ви можете додати власні обробники помилок за допомогою тих самих утиліт обробки помилок зі Starlette. Припустимо, у Вас є власний обʼєкт помилки `UnicornException`, яке Ви (або бібліотека, яку Ви використовуєте) може `згенерувати` (`raise`). diff --git a/docs/uk/docs/tutorial/middleware.md b/docs/uk/docs/tutorial/middleware.md index 807be484a..13ce8573d 100644 --- a/docs/uk/docs/tutorial/middleware.md +++ b/docs/uk/docs/tutorial/middleware.md @@ -39,7 +39,7 @@ Не забувайте, що власні заголовки можна додавати, використовуючи префікс 'X-'. -Але якщо у Вас є власні заголовки, які Ви хочете, щоб браузерний клієнт міг побачити, потрібно додати їх до Вашої конфігурації CORS (див. [CORS (Обмін ресурсами між різними джерелами)](cors.md){.internal-link target=_blank} за допомогою параметра `expose_headers`, описаного в документації Starlette по CORS. +Але якщо у Вас є власні заголовки, які Ви хочете, щоб браузерний клієнт міг побачити, потрібно додати їх до Вашої конфігурації CORS (див. [CORS (Обмін ресурсами між різними джерелами)](cors.md){.internal-link target=_blank} за допомогою параметра `expose_headers`, описаного в документації Starlette по CORS. /// diff --git a/docs/uk/docs/tutorial/static-files.md b/docs/uk/docs/tutorial/static-files.md index a84782d8f..3427f2376 100644 --- a/docs/uk/docs/tutorial/static-files.md +++ b/docs/uk/docs/tutorial/static-files.md @@ -37,4 +37,4 @@ ## Додаткова інформація -Детальніше про налаштування та можливості можна дізнатися в документації Starlette про статичні файли. +Детальніше про налаштування та можливості можна дізнатися в документації Starlette про статичні файли. diff --git a/docs/uk/docs/tutorial/testing.md b/docs/uk/docs/tutorial/testing.md index 25fc370d6..1105c6b0a 100644 --- a/docs/uk/docs/tutorial/testing.md +++ b/docs/uk/docs/tutorial/testing.md @@ -1,6 +1,6 @@ # Тестування -Тестування **FastAPI** додатків є простим та ефективним завдяки бібліотеці Starlette, яка базується на HTTPX. +Тестування **FastAPI** додатків є простим та ефективним завдяки бібліотеці Starlette, яка базується на HTTPX. Оскільки HTTPX розроблений на основі Requests, його API є інтуїтивно зрозумілим для тих, хто вже знайомий з Requests. З його допомогою Ви можете використовувати pytest безпосередньо з **FastAPI**. diff --git a/docs/vi/docs/fastapi-cli.md b/docs/vi/docs/fastapi-cli.md index d9e315ae4..e758f4d3a 100644 --- a/docs/vi/docs/fastapi-cli.md +++ b/docs/vi/docs/fastapi-cli.md @@ -52,7 +52,7 @@ FastAPI CLI nhận đường dẫn đến chương trình Python của bạn (vd Đối với vận hành thực tế (production), bạn sẽ sử dụng `fastapi run` thay thế. 🚀 -Ở bên trong, **FastAPI CLI** sử dụng Uvicorn, một server ASGI có hiệu suất cao, sẵn sàng cho vận hành thực tế (production). 😎 +Ở bên trong, **FastAPI CLI** sử dụng Uvicorn, một server ASGI có hiệu suất cao, sẵn sàng cho vận hành thực tế (production). 😎 ## `fastapi dev` diff --git a/docs/vi/docs/index.md b/docs/vi/docs/index.md index e7df2bf72..a5ac1bfb7 100644 --- a/docs/vi/docs/index.md +++ b/docs/vi/docs/index.md @@ -124,7 +124,7 @@ Nếu bạn đang xây dựng một CLIStarlette cho phần web. +* Starlette cho phần web. * Pydantic cho phần data. ## Cài đặt @@ -139,7 +139,7 @@ $ pip install fastapi
-Bạn cũng sẽ cần một ASGI server cho production như Uvicorn hoặc Hypercorn. +Bạn cũng sẽ cần một ASGI server cho production như Uvicorn hoặc Hypercorn.
@@ -464,7 +464,7 @@ Sử dụng Starlette: Sử dụng bởi FastAPI / Starlette: -* uvicorn - Server để chạy ứng dụng của bạn. +* uvicorn - Server để chạy ứng dụng của bạn. * orjson - Bắt buộc nếu bạn muốn sử dụng `ORJSONResponse`. * ujson - Bắt buộc nếu bạn muốn sử dụng `UJSONResponse`. diff --git a/docs/vi/docs/tutorial/first-steps.md b/docs/vi/docs/tutorial/first-steps.md index 901c8fd59..d1650539c 100644 --- a/docs/vi/docs/tutorial/first-steps.md +++ b/docs/vi/docs/tutorial/first-steps.md @@ -139,7 +139,7 @@ Bạn cũng có thể sử dụng nó để sinh code tự động, với các c `FastAPI` là một class kế thừa trực tiếp `Starlette`. -Bạn cũng có thể sử dụng tất cả Starlette chức năng với `FastAPI`. +Bạn cũng có thể sử dụng tất cả Starlette chức năng với `FastAPI`. /// diff --git a/docs/vi/docs/tutorial/static-files.md b/docs/vi/docs/tutorial/static-files.md index ecf8c2485..1bbec29e7 100644 --- a/docs/vi/docs/tutorial/static-files.md +++ b/docs/vi/docs/tutorial/static-files.md @@ -37,4 +37,4 @@ Tất cả các tham số này có thể khác với `static`, điều chỉnh c ## Thông tin thêm -Để biết thêm chi tiết và tùy chọn, hãy xem Starlette's docs about Static Files. +Để biết thêm chi tiết và tùy chọn, hãy xem Starlette's docs about Static Files. diff --git a/docs/zh-hant/docs/fastapi-cli.md b/docs/zh-hant/docs/fastapi-cli.md index 3c644ce46..b107e7e73 100644 --- a/docs/zh-hant/docs/fastapi-cli.md +++ b/docs/zh-hant/docs/fastapi-cli.md @@ -60,7 +60,7 @@ FastAPI CLI 接收你的 Python 程式路徑(例如 `main.py`),並自動 在生產環境,你應該使用 `fastapi run` 命令。 🚀 -**FastAPI CLI** 內部使用了 Uvicorn,這是一個高效能、適合生產環境的 ASGI 伺服器。 😎 +**FastAPI CLI** 內部使用了 Uvicorn,這是一個高效能、適合生產環境的 ASGI 伺服器。 😎 ## `fastapi dev` diff --git a/docs/zh-hant/docs/features.md b/docs/zh-hant/docs/features.md index 3a1392b51..f44d28a7f 100644 --- a/docs/zh-hant/docs/features.md +++ b/docs/zh-hant/docs/features.md @@ -167,7 +167,7 @@ FastAPI 有一個使用簡單,但是非常強大的Starlette的CORS文档中记录的`expose_headers`参数。 +但是,如果你有自定义头部,你希望浏览器中的客户端能够看到它们,你需要将它们添加到你的CORS配置中(在[CORS(跨源资源共享)](../tutorial/cors.md){.internal-link target=_blank}中阅读更多),使用在Starlette的CORS文档中记录的`expose_headers`参数。 diff --git a/docs/zh/docs/advanced/templates.md b/docs/zh/docs/advanced/templates.md index 8b7019ede..e627eed98 100644 --- a/docs/zh/docs/advanced/templates.md +++ b/docs/zh/docs/advanced/templates.md @@ -122,4 +122,4 @@ Item ID: 42 ## 更多说明 -包括测试模板等更多详情,请参阅 Starlette 官方文档 - 模板。 +包括测试模板等更多详情,请参阅 Starlette 官方文档 - 模板。 diff --git a/docs/zh/docs/advanced/testing-websockets.md b/docs/zh/docs/advanced/testing-websockets.md index 5d713d5f7..b84647a3e 100644 --- a/docs/zh/docs/advanced/testing-websockets.md +++ b/docs/zh/docs/advanced/testing-websockets.md @@ -8,6 +8,6 @@ /// note | 笔记 -更多细节详见 Starlette 官档 - 测试 WebSockets。 +更多细节详见 Starlette 官档 - 测试 WebSockets。 /// diff --git a/docs/zh/docs/advanced/using-request-directly.md b/docs/zh/docs/advanced/using-request-directly.md index db0fcafdf..a9658c034 100644 --- a/docs/zh/docs/advanced/using-request-directly.md +++ b/docs/zh/docs/advanced/using-request-directly.md @@ -15,7 +15,7 @@ ## `Request` 对象的细节 -实际上,**FastAPI** 的底层是 **Starlette**,**FastAPI** 只不过是在 **Starlette** 顶层提供了一些工具,所以能直接使用 Starlette 的 `Request` 对象。 +实际上,**FastAPI** 的底层是 **Starlette**,**FastAPI** 只不过是在 **Starlette** 顶层提供了一些工具,所以能直接使用 Starlette 的 `Request` 对象。 但直接从 `Request` 对象提取数据时(例如,读取请求体),**FastAPI** 不会验证、转换和存档数据(为 API 文档使用 OpenAPI)。 @@ -45,7 +45,7 @@ ## `Request` 文档 -更多细节详见 Starlette 官档 - `Request` 对象。 +更多细节详见 Starlette 官档 - `Request` 对象。 /// note | 技术细节 diff --git a/docs/zh/docs/advanced/websockets.md b/docs/zh/docs/advanced/websockets.md index d91aacc03..005ed9242 100644 --- a/docs/zh/docs/advanced/websockets.md +++ b/docs/zh/docs/advanced/websockets.md @@ -172,5 +172,5 @@ Client #1596980209979 left the chat 要了解更多选项,请查看 Starlette 的文档: -* [WebSocket 类](https://www.starlette.io/websockets/) -* [基于类的 WebSocket 处理](https://www.starlette.io/endpoints/#websocketendpoint)。 +* [WebSocket 类](https://www.starlette.dev/websockets/) +* [基于类的 WebSocket 处理](https://www.starlette.dev/endpoints/#websocketendpoint)。 diff --git a/docs/zh/docs/deployment/manually.md b/docs/zh/docs/deployment/manually.md index 3dc5942e3..2c2784a64 100644 --- a/docs/zh/docs/deployment/manually.md +++ b/docs/zh/docs/deployment/manually.md @@ -52,7 +52,7 @@ FastAPI 使用了一种用于构建 Python Web 框架和服务器的标准,称 除此之外,还有其他一些可选的 ASGI 服务器,例如: -* Uvicorn:高性能 ASGI 服务器。 +* Uvicorn:高性能 ASGI 服务器。 * Hypercorn:与 HTTP/2 和 Trio 等兼容的 ASGI 服务器。 * Daphne:为 Django Channels 构建的 ASGI 服务器。 * Granian:基于 Rust 的 HTTP 服务器,专为 Python 应用设计。 diff --git a/docs/zh/docs/fastapi-cli.md b/docs/zh/docs/fastapi-cli.md index 8a70e1d80..3b67eb664 100644 --- a/docs/zh/docs/fastapi-cli.md +++ b/docs/zh/docs/fastapi-cli.md @@ -52,7 +52,7 @@ FastAPI CLI 接收你的 Python 程序路径,自动检测包含 FastAPI 的变 在生产环境中,你应该使用 `fastapi run` 命令。🚀 -在内部,**FastAPI CLI** 使用了 Uvicorn,这是一个高性能、适用于生产环境的 ASGI 服务器。😎 +在内部,**FastAPI CLI** 使用了 Uvicorn,这是一个高性能、适用于生产环境的 ASGI 服务器。😎 ## `fastapi dev` diff --git a/docs/zh/docs/features.md b/docs/zh/docs/features.md index 24dc3e8ce..eaf8daff7 100644 --- a/docs/zh/docs/features.md +++ b/docs/zh/docs/features.md @@ -165,7 +165,7 @@ FastAPI 有一个使用非常简单,但是非常强大的. +更多细节查看 Starlette's official docs for Background Tasks. ## 告诫 diff --git a/docs/zh/docs/tutorial/first-steps.md b/docs/zh/docs/tutorial/first-steps.md index 80a34116a..2d7c35c8c 100644 --- a/docs/zh/docs/tutorial/first-steps.md +++ b/docs/zh/docs/tutorial/first-steps.md @@ -155,7 +155,7 @@ OpenAPI 为你的 API 定义 API 模式。该模式中包含了你的 API 发送 `FastAPI` 是直接从 `Starlette` 继承的类。 -你可以通过 `FastAPI` 使用所有的 Starlette 的功能。 +你可以通过 `FastAPI` 使用所有的 Starlette 的功能。 /// diff --git a/docs/zh/docs/tutorial/handling-errors.md b/docs/zh/docs/tutorial/handling-errors.md index 0b887c292..ae667b74a 100644 --- a/docs/zh/docs/tutorial/handling-errors.md +++ b/docs/zh/docs/tutorial/handling-errors.md @@ -83,7 +83,7 @@ ## 安装自定义异常处理器 -添加自定义处理器,要使用 [Starlette 的异常工具](https://www.starlette.io/exceptions/)。 +添加自定义处理器,要使用 [Starlette 的异常工具](https://www.starlette.dev/exceptions/)。 假设要触发的自定义异常叫作 `UnicornException`。 diff --git a/docs/zh/docs/tutorial/middleware.md b/docs/zh/docs/tutorial/middleware.md index 258ca7482..5608c4ee1 100644 --- a/docs/zh/docs/tutorial/middleware.md +++ b/docs/zh/docs/tutorial/middleware.md @@ -37,7 +37,7 @@ 请记住可以 用'X-' 前缀添加专有自定义请求头. -但是如果你想让浏览器中的客户端看到你的自定义请求头, 你需要把它们加到 CORS 配置 ([CORS (Cross-Origin Resource Sharing)](cors.md){.internal-link target=_blank}) 的 `expose_headers` 参数中,在 Starlette's CORS docs文档中. +但是如果你想让浏览器中的客户端看到你的自定义请求头, 你需要把它们加到 CORS 配置 ([CORS (Cross-Origin Resource Sharing)](cors.md){.internal-link target=_blank}) 的 `expose_headers` 参数中,在 Starlette's CORS docs文档中. /// diff --git a/docs/zh/docs/tutorial/static-files.md b/docs/zh/docs/tutorial/static-files.md index c19079565..1a0d4504c 100644 --- a/docs/zh/docs/tutorial/static-files.md +++ b/docs/zh/docs/tutorial/static-files.md @@ -37,4 +37,4 @@ ## 更多信息 -更多细节和选择查阅 Starlette's docs about Static Files. +更多细节和选择查阅 Starlette's docs about Static Files. diff --git a/docs/zh/docs/tutorial/testing.md b/docs/zh/docs/tutorial/testing.md index 3e0c48caf..3877adbac 100644 --- a/docs/zh/docs/tutorial/testing.md +++ b/docs/zh/docs/tutorial/testing.md @@ -1,6 +1,6 @@ # 测试 -感谢 Starlette,测试**FastAPI** 应用轻松又愉快。 +感谢 Starlette,测试**FastAPI** 应用轻松又愉快。 它基于 HTTPX, 而HTTPX又是基于Requests设计的,所以很相似且易懂。 diff --git a/docs_src/dependencies/tutorial008e.py b/docs_src/dependencies/tutorial008e.py new file mode 100644 index 000000000..1ed056e91 --- /dev/null +++ b/docs_src/dependencies/tutorial008e.py @@ -0,0 +1,15 @@ +from fastapi import Depends, FastAPI + +app = FastAPI() + + +def get_username(): + try: + yield "Rick" + finally: + print("Cleanup up before response is sent") + + +@app.get("/users/me") +def get_user_me(username: str = Depends(get_username, scope="function")): + return username diff --git a/docs_src/dependencies/tutorial008e_an.py b/docs_src/dependencies/tutorial008e_an.py new file mode 100644 index 000000000..c8a0af2b3 --- /dev/null +++ b/docs_src/dependencies/tutorial008e_an.py @@ -0,0 +1,16 @@ +from fastapi import Depends, FastAPI +from typing_extensions import Annotated + +app = FastAPI() + + +def get_username(): + try: + yield "Rick" + finally: + print("Cleanup up before response is sent") + + +@app.get("/users/me") +def get_user_me(username: Annotated[str, Depends(get_username, scope="function")]): + return username diff --git a/docs_src/dependencies/tutorial008e_an_py39.py b/docs_src/dependencies/tutorial008e_an_py39.py new file mode 100644 index 000000000..80a44c7e2 --- /dev/null +++ b/docs_src/dependencies/tutorial008e_an_py39.py @@ -0,0 +1,17 @@ +from typing import Annotated + +from fastapi import Depends, FastAPI + +app = FastAPI() + + +def get_username(): + try: + yield "Rick" + finally: + print("Cleanup up before response is sent") + + +@app.get("/users/me") +def get_user_me(username: Annotated[str, Depends(get_username, scope="function")]): + return username diff --git a/docs_src/dependencies/tutorial013a.py b/docs_src/dependencies/tutorial013a.py index 83687af24..423e3be18 100644 --- a/docs_src/dependencies/tutorial013a.py +++ b/docs_src/dependencies/tutorial013a.py @@ -27,7 +27,7 @@ async def get_database_connection(): yield connection -GlobalDatabaseConnection = Depends(get_database_connection, dependency_scope="lifespan") +GlobalDatabaseConnection = Depends(get_database_connection, scope="lifespan") @app.get("/users/") diff --git a/docs_src/dependencies/tutorial013a_an_py39.py b/docs_src/dependencies/tutorial013a_an_py39.py index 62f10a6e1..d30d75d5d 100644 --- a/docs_src/dependencies/tutorial013a_an_py39.py +++ b/docs_src/dependencies/tutorial013a_an_py39.py @@ -28,7 +28,7 @@ async def get_database_connection(): GlobalDatabaseConnection = Annotated[ - MyDatabaseConnection, Depends(get_database_connection, dependency_scope="lifespan") + MyDatabaseConnection, Depends(get_database_connection, scope="lifespan") ] diff --git a/docs_src/dependencies/tutorial013b.py b/docs_src/dependencies/tutorial013b.py index 3123b64f5..789254a57 100644 --- a/docs_src/dependencies/tutorial013b.py +++ b/docs_src/dependencies/tutorial013b.py @@ -30,9 +30,9 @@ async def get_database_connection(): yield connection -GlobalDatabaseConnection = Depends(get_database_connection, dependency_scope="lifespan") +GlobalDatabaseConnection = Depends(get_database_connection, scope="lifespan") DedicatedDatabaseConnection = Depends( - get_database_connection, dependency_scope="lifespan", use_cache=False + get_database_connection, scope="lifespan", use_cache=False ) diff --git a/docs_src/dependencies/tutorial013b_an_py39.py b/docs_src/dependencies/tutorial013b_an_py39.py index cc7205f40..af3475c26 100644 --- a/docs_src/dependencies/tutorial013b_an_py39.py +++ b/docs_src/dependencies/tutorial013b_an_py39.py @@ -31,11 +31,11 @@ async def get_database_connection(): GlobalDatabaseConnection = Annotated[ - MyDatabaseConnection, Depends(get_database_connection, dependency_scope="lifespan") + MyDatabaseConnection, Depends(get_database_connection, scope="lifespan") ] DedicatedDatabaseConnection = Annotated[ MyDatabaseConnection, - Depends(get_database_connection, dependency_scope="lifespan", use_cache=False), + Depends(get_database_connection, scope="lifespan", use_cache=False), ] diff --git a/docs_src/dependencies/tutorial013c.py b/docs_src/dependencies/tutorial013c.py index c8814adc0..dcd1bac73 100644 --- a/docs_src/dependencies/tutorial013c.py +++ b/docs_src/dependencies/tutorial013c.py @@ -31,7 +31,7 @@ async def get_configuration() -> dict: } -GlobalConfiguration = Depends(get_configuration, dependency_scope="lifespan") +GlobalConfiguration = Depends(get_configuration, scope="lifespan") async def get_database_connection(configuration: dict = GlobalConfiguration): @@ -39,7 +39,7 @@ async def get_database_connection(configuration: dict = GlobalConfiguration): yield connection -GlobalDatabaseConnection = Depends(get_database_connection, dependency_scope="lifespan") +GlobalDatabaseConnection = Depends(get_database_connection, scope="lifespan") @app.get("/users/{user_id}") diff --git a/docs_src/dependencies/tutorial013c_an_py39.py b/docs_src/dependencies/tutorial013c_an_py39.py index a64e72b8a..d9fcceed2 100644 --- a/docs_src/dependencies/tutorial013c_an_py39.py +++ b/docs_src/dependencies/tutorial013c_an_py39.py @@ -33,7 +33,7 @@ async def get_configuration() -> dict: GlobalConfiguration = Annotated[ - dict, Depends(get_configuration, dependency_scope="lifespan") + dict, Depends(get_configuration, scope="lifespan") ] @@ -44,7 +44,7 @@ async def get_database_connection(configuration: GlobalConfiguration): GlobalDatabaseConnection = Annotated[ get_database_connection, - Depends(get_database_connection, dependency_scope="lifespan"), + Depends(get_database_connection, scope="lifespan"), ] diff --git a/docs_src/dependencies/tutorial013d.py b/docs_src/dependencies/tutorial013d.py index 01e2831d7..8543c159a 100644 --- a/docs_src/dependencies/tutorial013d.py +++ b/docs_src/dependencies/tutorial013d.py @@ -25,7 +25,7 @@ async def get_database_connection(): yield connection -GlobalDatabaseConnection = Depends(get_database_connection, dependency_scope="lifespan") +GlobalDatabaseConnection = Depends(get_database_connection, scope="lifespan") async def get_user_record( diff --git a/docs_src/dependencies/tutorial013d_an_py39.py b/docs_src/dependencies/tutorial013d_an_py39.py index fa6b0831b..77c0494e6 100644 --- a/docs_src/dependencies/tutorial013d_an_py39.py +++ b/docs_src/dependencies/tutorial013d_an_py39.py @@ -28,7 +28,7 @@ async def get_database_connection(): GlobalDatabaseConnection = Annotated[ - MyDatabaseConnection, Depends(get_database_connection, dependency_scope="lifespan") + MyDatabaseConnection, Depends(get_database_connection, scope="lifespan") ] diff --git a/fastapi/__init__.py b/fastapi/__init__.py index 2091f0d1f..f4a952bf5 100644 --- a/fastapi/__init__.py +++ b/fastapi/__init__.py @@ -1,6 +1,6 @@ """FastAPI framework, high performance, easy to learn, fast to code, ready for production""" -__version__ = "0.119.0" +__version__ = "0.121.0" from starlette import status as status diff --git a/fastapi/_compat/__init__.py b/fastapi/_compat/__init__.py index b2ae5adc7..0aadd68de 100644 --- a/fastapi/_compat/__init__.py +++ b/fastapi/_compat/__init__.py @@ -30,6 +30,10 @@ from .main import serialize_sequence_value as serialize_sequence_value from .main import ( with_info_plain_validator_function as with_info_plain_validator_function, ) +from .may_v1 import CoreSchema as CoreSchema +from .may_v1 import GetJsonSchemaHandler as GetJsonSchemaHandler +from .may_v1 import JsonSchemaValue as JsonSchemaValue +from .may_v1 import _normalize_errors as _normalize_errors from .model_field import ModelField as ModelField from .shared import PYDANTIC_V2 as PYDANTIC_V2 from .shared import PYDANTIC_VERSION_MINOR_TUPLE as PYDANTIC_VERSION_MINOR_TUPLE @@ -44,7 +48,3 @@ from .shared import ( from .shared import lenient_issubclass as lenient_issubclass from .shared import sequence_types as sequence_types from .shared import value_is_sequence as value_is_sequence -from .v1 import CoreSchema as CoreSchema -from .v1 import GetJsonSchemaHandler as GetJsonSchemaHandler -from .v1 import JsonSchemaValue as JsonSchemaValue -from .v1 import _normalize_errors as _normalize_errors diff --git a/fastapi/_compat/main.py b/fastapi/_compat/main.py index 3f758f072..e5275950e 100644 --- a/fastapi/_compat/main.py +++ b/fastapi/_compat/main.py @@ -1,3 +1,4 @@ +import sys from functools import lru_cache from typing import ( Any, @@ -8,7 +9,7 @@ from typing import ( Type, ) -from fastapi._compat import v1 +from fastapi._compat import may_v1 from fastapi._compat.shared import PYDANTIC_V2, lenient_issubclass from fastapi.types import ModelNameMap from pydantic import BaseModel @@ -50,7 +51,9 @@ else: @lru_cache def get_cached_model_fields(model: Type[BaseModel]) -> List[ModelField]: - if lenient_issubclass(model, v1.BaseModel): + if lenient_issubclass(model, may_v1.BaseModel): + from fastapi._compat import v1 + return v1.get_model_fields(model) else: from . import v2 @@ -59,7 +62,7 @@ def get_cached_model_fields(model: Type[BaseModel]) -> List[ModelField]: def _is_undefined(value: object) -> bool: - if isinstance(value, v1.UndefinedType): + if isinstance(value, may_v1.UndefinedType): return True elif PYDANTIC_V2: from . import v2 @@ -69,7 +72,9 @@ def _is_undefined(value: object) -> bool: def _get_model_config(model: BaseModel) -> Any: - if isinstance(model, v1.BaseModel): + if isinstance(model, may_v1.BaseModel): + from fastapi._compat import v1 + return v1._get_model_config(model) elif PYDANTIC_V2: from . import v2 @@ -80,7 +85,9 @@ def _get_model_config(model: BaseModel) -> Any: def _model_dump( model: BaseModel, mode: Literal["json", "python"] = "json", **kwargs: Any ) -> Any: - if isinstance(model, v1.BaseModel): + if isinstance(model, may_v1.BaseModel): + from fastapi._compat import v1 + return v1._model_dump(model, mode=mode, **kwargs) elif PYDANTIC_V2: from . import v2 @@ -89,7 +96,7 @@ def _model_dump( def _is_error_wrapper(exc: Exception) -> bool: - if isinstance(exc, v1.ErrorWrapper): + if isinstance(exc, may_v1.ErrorWrapper): return True elif PYDANTIC_V2: from . import v2 @@ -99,7 +106,9 @@ def _is_error_wrapper(exc: Exception) -> bool: def copy_field_info(*, field_info: FieldInfo, annotation: Any) -> FieldInfo: - if isinstance(field_info, v1.FieldInfo): + if isinstance(field_info, may_v1.FieldInfo): + from fastapi._compat import v1 + return v1.copy_field_info(field_info=field_info, annotation=annotation) else: assert PYDANTIC_V2 @@ -111,7 +120,9 @@ def copy_field_info(*, field_info: FieldInfo, annotation: Any) -> FieldInfo: def create_body_model( *, fields: Sequence[ModelField], model_name: str ) -> Type[BaseModel]: - if fields and isinstance(fields[0], v1.ModelField): + if fields and isinstance(fields[0], may_v1.ModelField): + from fastapi._compat import v1 + return v1.create_body_model(fields=fields, model_name=model_name) else: assert PYDANTIC_V2 @@ -123,7 +134,9 @@ def create_body_model( def get_annotation_from_field_info( annotation: Any, field_info: FieldInfo, field_name: str ) -> Any: - if isinstance(field_info, v1.FieldInfo): + if isinstance(field_info, may_v1.FieldInfo): + from fastapi._compat import v1 + return v1.get_annotation_from_field_info( annotation=annotation, field_info=field_info, field_name=field_name ) @@ -137,7 +150,9 @@ def get_annotation_from_field_info( def is_bytes_field(field: ModelField) -> bool: - if isinstance(field, v1.ModelField): + if isinstance(field, may_v1.ModelField): + from fastapi._compat import v1 + return v1.is_bytes_field(field) else: assert PYDANTIC_V2 @@ -147,7 +162,9 @@ def is_bytes_field(field: ModelField) -> bool: def is_bytes_sequence_field(field: ModelField) -> bool: - if isinstance(field, v1.ModelField): + if isinstance(field, may_v1.ModelField): + from fastapi._compat import v1 + return v1.is_bytes_sequence_field(field) else: assert PYDANTIC_V2 @@ -157,7 +174,9 @@ def is_bytes_sequence_field(field: ModelField) -> bool: def is_scalar_field(field: ModelField) -> bool: - if isinstance(field, v1.ModelField): + if isinstance(field, may_v1.ModelField): + from fastapi._compat import v1 + return v1.is_scalar_field(field) else: assert PYDANTIC_V2 @@ -167,7 +186,9 @@ def is_scalar_field(field: ModelField) -> bool: def is_scalar_sequence_field(field: ModelField) -> bool: - if isinstance(field, v1.ModelField): + if isinstance(field, may_v1.ModelField): + from fastapi._compat import v1 + return v1.is_scalar_sequence_field(field) else: assert PYDANTIC_V2 @@ -177,7 +198,9 @@ def is_scalar_sequence_field(field: ModelField) -> bool: def is_sequence_field(field: ModelField) -> bool: - if isinstance(field, v1.ModelField): + if isinstance(field, may_v1.ModelField): + from fastapi._compat import v1 + return v1.is_sequence_field(field) else: assert PYDANTIC_V2 @@ -187,7 +210,9 @@ def is_sequence_field(field: ModelField) -> bool: def serialize_sequence_value(*, field: ModelField, value: Any) -> Sequence[Any]: - if isinstance(field, v1.ModelField): + if isinstance(field, may_v1.ModelField): + from fastapi._compat import v1 + return v1.serialize_sequence_value(field=field, value=value) else: assert PYDANTIC_V2 @@ -197,7 +222,9 @@ def serialize_sequence_value(*, field: ModelField, value: Any) -> Sequence[Any]: def _model_rebuild(model: Type[BaseModel]) -> None: - if lenient_issubclass(model, v1.BaseModel): + if lenient_issubclass(model, may_v1.BaseModel): + from fastapi._compat import v1 + v1._model_rebuild(model) elif PYDANTIC_V2: from . import v2 @@ -206,9 +233,18 @@ def _model_rebuild(model: Type[BaseModel]) -> None: def get_compat_model_name_map(fields: List[ModelField]) -> ModelNameMap: - v1_model_fields = [field for field in fields if isinstance(field, v1.ModelField)] - v1_flat_models = v1.get_flat_models_from_fields(v1_model_fields, known_models=set()) # type: ignore[attr-defined] - all_flat_models = v1_flat_models + v1_model_fields = [ + field for field in fields if isinstance(field, may_v1.ModelField) + ] + if v1_model_fields: + from fastapi._compat import v1 + + v1_flat_models = v1.get_flat_models_from_fields( + v1_model_fields, known_models=set() + ) + all_flat_models = v1_flat_models + else: + all_flat_models = set() if PYDANTIC_V2: from . import v2 @@ -222,6 +258,8 @@ def get_compat_model_name_map(fields: List[ModelField]) -> ModelNameMap: model_name_map = v2.get_model_name_map(all_flat_models) return model_name_map + from fastapi._compat import v1 + model_name_map = v1.get_model_name_map(all_flat_models) return model_name_map @@ -232,17 +270,35 @@ def get_definitions( model_name_map: ModelNameMap, separate_input_output_schemas: bool = True, ) -> Tuple[ - Dict[Tuple[ModelField, Literal["validation", "serialization"]], v1.JsonSchemaValue], + Dict[ + Tuple[ModelField, Literal["validation", "serialization"]], + may_v1.JsonSchemaValue, + ], Dict[str, Dict[str, Any]], ]: - v1_fields = [field for field in fields if isinstance(field, v1.ModelField)] - v1_field_maps, v1_definitions = v1.get_definitions( - fields=v1_fields, - model_name_map=model_name_map, - separate_input_output_schemas=separate_input_output_schemas, - ) - if not PYDANTIC_V2: - return v1_field_maps, v1_definitions + if sys.version_info < (3, 14): + v1_fields = [field for field in fields if isinstance(field, may_v1.ModelField)] + v1_field_maps, v1_definitions = may_v1.get_definitions( + fields=v1_fields, + model_name_map=model_name_map, + separate_input_output_schemas=separate_input_output_schemas, + ) + if not PYDANTIC_V2: + return v1_field_maps, v1_definitions + else: + from . import v2 + + v2_fields = [field for field in fields if isinstance(field, v2.ModelField)] + v2_field_maps, v2_definitions = v2.get_definitions( + fields=v2_fields, + model_name_map=model_name_map, + separate_input_output_schemas=separate_input_output_schemas, + ) + all_definitions = {**v1_definitions, **v2_definitions} + all_field_maps = {**v1_field_maps, **v2_field_maps} + return all_field_maps, all_definitions + + # Pydantic v1 is not supported since Python 3.14 else: from . import v2 @@ -252,9 +308,7 @@ def get_definitions( model_name_map=model_name_map, separate_input_output_schemas=separate_input_output_schemas, ) - all_definitions = {**v1_definitions, **v2_definitions} - all_field_maps = {**v1_field_maps, **v2_field_maps} - return all_field_maps, all_definitions + return v2_field_maps, v2_definitions def get_schema_from_model_field( @@ -262,11 +316,14 @@ def get_schema_from_model_field( field: ModelField, model_name_map: ModelNameMap, field_mapping: Dict[ - Tuple[ModelField, Literal["validation", "serialization"]], v1.JsonSchemaValue + Tuple[ModelField, Literal["validation", "serialization"]], + may_v1.JsonSchemaValue, ], separate_input_output_schemas: bool = True, ) -> Dict[str, Any]: - if isinstance(field, v1.ModelField): + if isinstance(field, may_v1.ModelField): + from fastapi._compat import v1 + return v1.get_schema_from_model_field( field=field, model_name_map=model_name_map, @@ -286,7 +343,7 @@ def get_schema_from_model_field( def _is_model_field(value: Any) -> bool: - if isinstance(value, v1.ModelField): + if isinstance(value, may_v1.ModelField): return True elif PYDANTIC_V2: from . import v2 @@ -296,7 +353,7 @@ def _is_model_field(value: Any) -> bool: def _is_model_class(value: Any) -> bool: - if lenient_issubclass(value, v1.BaseModel): + if lenient_issubclass(value, may_v1.BaseModel): return True elif PYDANTIC_V2: from . import v2 diff --git a/fastapi/_compat/may_v1.py b/fastapi/_compat/may_v1.py new file mode 100644 index 000000000..beea4d167 --- /dev/null +++ b/fastapi/_compat/may_v1.py @@ -0,0 +1,123 @@ +import sys +from typing import Any, Dict, List, Literal, Sequence, Tuple, Type, Union + +from fastapi.types import ModelNameMap + +if sys.version_info >= (3, 14): + + class AnyUrl: + pass + + class BaseConfig: + pass + + class BaseModel: + pass + + class Color: + pass + + class CoreSchema: + pass + + class ErrorWrapper: + pass + + class FieldInfo: + pass + + class GetJsonSchemaHandler: + pass + + class JsonSchemaValue: + pass + + class ModelField: + pass + + class NameEmail: + pass + + class RequiredParam: + pass + + class SecretBytes: + pass + + class SecretStr: + pass + + class Undefined: + pass + + class UndefinedType: + pass + + class Url: + pass + + from .v2 import ValidationError, create_model + + def get_definitions( + *, + fields: List[ModelField], + model_name_map: ModelNameMap, + separate_input_output_schemas: bool = True, + ) -> Tuple[ + Dict[ + Tuple[ModelField, Literal["validation", "serialization"]], JsonSchemaValue + ], + Dict[str, Dict[str, Any]], + ]: + return {}, {} # pragma: no cover + + +else: + from .v1 import AnyUrl as AnyUrl + from .v1 import BaseConfig as BaseConfig + from .v1 import BaseModel as BaseModel + from .v1 import Color as Color + from .v1 import CoreSchema as CoreSchema + from .v1 import ErrorWrapper as ErrorWrapper + from .v1 import FieldInfo as FieldInfo + from .v1 import GetJsonSchemaHandler as GetJsonSchemaHandler + from .v1 import JsonSchemaValue as JsonSchemaValue + from .v1 import ModelField as ModelField + from .v1 import NameEmail as NameEmail + from .v1 import RequiredParam as RequiredParam + from .v1 import SecretBytes as SecretBytes + from .v1 import SecretStr as SecretStr + from .v1 import Undefined as Undefined + from .v1 import UndefinedType as UndefinedType + from .v1 import Url as Url + from .v1 import ValidationError, create_model + from .v1 import get_definitions as get_definitions + + +RequestErrorModel: Type[BaseModel] = create_model("Request") + + +def _normalize_errors(errors: Sequence[Any]) -> List[Dict[str, Any]]: + use_errors: List[Any] = [] + for error in errors: + if isinstance(error, ErrorWrapper): + new_errors = ValidationError( # type: ignore[call-arg] + errors=[error], model=RequestErrorModel + ).errors() + use_errors.extend(new_errors) + elif isinstance(error, list): + use_errors.extend(_normalize_errors(error)) + else: + use_errors.append(error) + return use_errors + + +def _regenerate_error_with_loc( + *, errors: Sequence[Any], loc_prefix: Tuple[Union[str, int], ...] +) -> List[Dict[str, Any]]: + updated_loc_errors: List[Any] = [ + {**err, "loc": loc_prefix + err.get("loc", ())} + for err in _normalize_errors(errors) + ] + + return updated_loc_errors diff --git a/fastapi/_compat/shared.py b/fastapi/_compat/shared.py index 495d5c5f7..cabf48228 100644 --- a/fastapi/_compat/shared.py +++ b/fastapi/_compat/shared.py @@ -16,7 +16,7 @@ from typing import ( Union, ) -from fastapi._compat import v1 +from fastapi._compat import may_v1 from fastapi.types import UnionType from pydantic import BaseModel from pydantic.version import VERSION as PYDANTIC_VERSION @@ -98,7 +98,9 @@ def value_is_sequence(value: Any) -> bool: def _annotation_is_complex(annotation: Union[Type[Any], None]) -> bool: return ( - lenient_issubclass(annotation, (BaseModel, v1.BaseModel, Mapping, UploadFile)) + lenient_issubclass( + annotation, (BaseModel, may_v1.BaseModel, Mapping, UploadFile) + ) or _annotation_is_sequence(annotation) or is_dataclass(annotation) ) @@ -195,12 +197,12 @@ def is_uploadfile_sequence_annotation(annotation: Any) -> bool: def annotation_is_pydantic_v1(annotation: Any) -> bool: - if lenient_issubclass(annotation, v1.BaseModel): + if lenient_issubclass(annotation, may_v1.BaseModel): return True origin = get_origin(annotation) if origin is Union or origin is UnionType: for arg in get_args(annotation): - if lenient_issubclass(arg, v1.BaseModel): + if lenient_issubclass(arg, may_v1.BaseModel): return True if field_annotation_is_sequence(annotation): for sub_annotation in get_args(annotation): diff --git a/fastapi/_compat/v1.py b/fastapi/_compat/v1.py index f0ac51634..e17ce8bea 100644 --- a/fastapi/_compat/v1.py +++ b/fastapi/_compat/v1.py @@ -54,13 +54,15 @@ if not PYDANTIC_V2: from pydantic.schema import TypeModelSet as TypeModelSet from pydantic.schema import ( field_schema, - get_flat_models_from_fields, model_process_schema, ) from pydantic.schema import ( get_annotation_from_field_info as get_annotation_from_field_info, ) from pydantic.schema import get_flat_models_from_field as get_flat_models_from_field + from pydantic.schema import ( + get_flat_models_from_fields as get_flat_models_from_fields, + ) from pydantic.schema import get_model_name_map as get_model_name_map from pydantic.types import SecretBytes as SecretBytes from pydantic.types import SecretStr as SecretStr @@ -99,7 +101,6 @@ else: from pydantic.v1.schema import TypeModelSet as TypeModelSet from pydantic.v1.schema import ( field_schema, - get_flat_models_from_fields, model_process_schema, ) from pydantic.v1.schema import ( @@ -108,6 +109,9 @@ else: from pydantic.v1.schema import ( get_flat_models_from_field as get_flat_models_from_field, ) + from pydantic.v1.schema import ( + get_flat_models_from_fields as get_flat_models_from_fields, + ) from pydantic.v1.schema import get_model_name_map as get_model_name_map from pydantic.v1.types import ( # type: ignore[assignment] SecretBytes as SecretBytes, @@ -215,32 +219,6 @@ def is_pv1_scalar_sequence_field(field: ModelField) -> bool: return False -def _normalize_errors(errors: Sequence[Any]) -> List[Dict[str, Any]]: - use_errors: List[Any] = [] - for error in errors: - if isinstance(error, ErrorWrapper): - new_errors = ValidationError( # type: ignore[call-arg] - errors=[error], model=RequestErrorModel - ).errors() - use_errors.extend(new_errors) - elif isinstance(error, list): - use_errors.extend(_normalize_errors(error)) - else: - use_errors.append(error) - return use_errors - - -def _regenerate_error_with_loc( - *, errors: Sequence[Any], loc_prefix: Tuple[Union[str, int], ...] -) -> List[Dict[str, Any]]: - updated_loc_errors: List[Any] = [ - {**err, "loc": loc_prefix + err.get("loc", ())} - for err in _normalize_errors(errors) - ] - - return updated_loc_errors - - def _model_rebuild(model: Type[BaseModel]) -> None: model.update_forward_refs() diff --git a/fastapi/_compat/v2.py b/fastapi/_compat/v2.py index 29606b9f3..6a87b9ae9 100644 --- a/fastapi/_compat/v2.py +++ b/fastapi/_compat/v2.py @@ -15,7 +15,7 @@ from typing import ( cast, ) -from fastapi._compat import shared, v1 +from fastapi._compat import may_v1, shared from fastapi.openapi.constants import REF_TEMPLATE from fastapi.types import IncEx, ModelNameMap from pydantic import BaseModel, TypeAdapter, create_model @@ -116,7 +116,7 @@ class ModelField: None, ) except ValidationError as exc: - return None, v1._regenerate_error_with_loc( + return None, may_v1._regenerate_error_with_loc( errors=exc.errors(include_url=False), loc_prefix=loc ) @@ -207,11 +207,31 @@ def get_definitions( override_mode: Union[Literal["validation"], None] = ( None if separate_input_output_schemas else "validation" ) - flat_models = get_flat_models_from_fields(fields, known_models=set()) - flat_model_fields = [ - ModelField(field_info=FieldInfo(annotation=model), name=model.__name__) - for model in flat_models + validation_fields = [field for field in fields if field.mode == "validation"] + serialization_fields = [field for field in fields if field.mode == "serialization"] + flat_validation_models = get_flat_models_from_fields( + validation_fields, known_models=set() + ) + flat_serialization_models = get_flat_models_from_fields( + serialization_fields, known_models=set() + ) + flat_validation_model_fields = [ + ModelField( + field_info=FieldInfo(annotation=model), + name=model.__name__, + mode="validation", + ) + for model in flat_validation_models + ] + flat_serialization_model_fields = [ + ModelField( + field_info=FieldInfo(annotation=model), + name=model.__name__, + mode="serialization", + ) + for model in flat_serialization_models ] + flat_model_fields = flat_validation_model_fields + flat_serialization_model_fields input_types = {f.type_ for f in fields} unique_flat_model_fields = { f for f in flat_model_fields if f.type_ not in input_types diff --git a/fastapi/applications.py b/fastapi/applications.py index 1c0d410df..864611121 100644 --- a/fastapi/applications.py +++ b/fastapi/applications.py @@ -15,9 +15,9 @@ from typing import ( Union, ) +from annotated_doc import Doc from fastapi import routing from fastapi.datastructures import Default, DefaultPlaceholder -from fastapi.dependencies.utils import is_coroutine_callable from fastapi.exception_handlers import ( http_exception_handler, request_validation_exception_handler, @@ -36,7 +36,7 @@ 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 +from fastapi.utils import generate_unique_id, call_asynchronously from starlette.applications import Starlette from starlette.concurrency import run_in_threadpool from starlette.datastructures import State @@ -49,7 +49,7 @@ from starlette.requests import Request from starlette.responses import HTMLResponse, JSONResponse, Response from starlette.routing import BaseRoute from starlette.types import ASGIApp, ExceptionHandler, Lifespan, Receive, Scope, Send -from typing_extensions import Annotated, Doc, deprecated +from typing_extensions import Annotated, deprecated AppType = TypeVar("AppType", bound="FastAPI") @@ -81,7 +81,7 @@ class FastAPI(Starlette): errors. Read more in the - [Starlette docs for Applications](https://www.starlette.io/applications/#instantiating-the-application). + [Starlette docs for Applications](https://www.starlette.dev/applications/#instantiating-the-application). """ ), ] = False, @@ -944,7 +944,7 @@ class FastAPI(Starlette): This is simply inherited from Starlette. Read more about it in the - [Starlette docs for Applications](https://www.starlette.io/applications/#storing-state-on-the-app-instance). + [Starlette docs for Applications](https://www.starlette.dev/applications/#storing-state-on-the-app-instance). """ ), ] = State() @@ -1069,10 +1069,7 @@ class FastAPI(Starlette): ) try: for handler in self._on_startup: - if is_coroutine_callable(handler): - await handler() - else: - await run_in_threadpool(handler) + await call_asynchronously(handler) yield { "__fastapi__": { "lifespan_scoped_dependencies": lifespan_scoped_dependencies @@ -1080,10 +1077,7 @@ class FastAPI(Starlette): } finally: for handler in self._on_shutdown: - if is_coroutine_callable(handler): - await handler() - else: - await run_in_threadpool(handler) + await call_asynchronously(handler) def openapi(self) -> Dict[str, Any]: """ diff --git a/fastapi/background.py b/fastapi/background.py index 203578a41..6d4a30d44 100644 --- a/fastapi/background.py +++ b/fastapi/background.py @@ -1,7 +1,8 @@ from typing import Any, Callable +from annotated_doc import Doc from starlette.background import BackgroundTasks as StarletteBackgroundTasks -from typing_extensions import Annotated, Doc, ParamSpec +from typing_extensions import Annotated, ParamSpec P = ParamSpec("P") diff --git a/fastapi/datastructures.py b/fastapi/datastructures.py index 34185b96a..8ad9aa11a 100644 --- a/fastapi/datastructures.py +++ b/fastapi/datastructures.py @@ -10,6 +10,7 @@ from typing import ( cast, ) +from annotated_doc import Doc from fastapi._compat import ( CoreSchema, GetJsonSchemaHandler, @@ -22,7 +23,7 @@ from starlette.datastructures import Headers as Headers # noqa: F401 from starlette.datastructures import QueryParams as QueryParams # noqa: F401 from starlette.datastructures import State as State # noqa: F401 from starlette.datastructures import UploadFile as StarletteUploadFile -from typing_extensions import Annotated, Doc +from typing_extensions import Annotated class UploadFile(StarletteUploadFile): diff --git a/fastapi/dependencies/models.py b/fastapi/dependencies/models.py index 1f4192a51..22df740c9 100644 --- a/fastapi/dependencies/models.py +++ b/fastapi/dependencies/models.py @@ -1,9 +1,18 @@ +import inspect +import sys from dataclasses import dataclass, field -from typing import Any, Callable, List, Optional, Sequence, Tuple, Union, cast +from functools import cached_property +from typing import Any, Callable, List, Optional, Sequence, Union, Tuple, cast from fastapi._compat import ModelField from fastapi.security.base import SecurityBase -from typing_extensions import TypeAlias +from fastapi.types import EndpointDependencyCacheKey, LifespanDependencyCacheKey +from typing_extensions import Literal, TypeAlias + +if sys.version_info >= (3, 13): # pragma: no cover + from inspect import iscoroutinefunction +else: # pragma: no cover + from asyncio import iscoroutinefunction @dataclass @@ -12,11 +21,6 @@ class SecurityRequirement: scopes: Optional[Sequence[str]] = None -LifespanDependantCacheKey: TypeAlias = Union[ - Tuple[Callable[..., Any], Union[str, int]], Callable[..., Any] -] - - @dataclass class LifespanDependant: call: Callable[..., Any] @@ -25,40 +29,55 @@ class LifespanDependant: name: Optional[str] = None use_cache: bool = True index: Optional[int] = None - cache_key: LifespanDependantCacheKey = field(init=False) - def __post_init__(self) -> None: + @cached_property + def is_gen_callable(self) -> bool: + if inspect.isgeneratorfunction(self.call): + return True + dunder_call = getattr(self.call, "__call__", None) # noqa: B004 + return inspect.isgeneratorfunction(dunder_call) + + @cached_property + def is_async_gen_callable(self) -> bool: + if inspect.isasyncgenfunction(self.call): + return True + dunder_call = getattr(self.call, "__call__", None) # noqa: B004 + return inspect.isasyncgenfunction(dunder_call) + + @cached_property + def is_coroutine_callable(self) -> bool: + if inspect.isroutine(self.call): + return iscoroutinefunction(self.call) + if inspect.isclass(self.call): + return False + dunder_call = getattr(self.call, "__call__", None) # noqa: B004 + return iscoroutinefunction(dunder_call) + + @cached_property + def cache_key(self) -> LifespanDependencyCacheKey: if self.use_cache: - self.cache_key = self.call + return self.call elif self.name is not None: - self.cache_key = (self.caller, self.name) + return self.caller, self.name else: assert self.index is not None, ( "Lifespan dependency must have an associated name or index." ) - self.cache_key = (self.caller, self.index) - - -EndpointDependantCacheKey: TypeAlias = Tuple[ - Optional[Callable[..., Any]], Tuple[str, ...] -] - + return self.caller, self.index @dataclass class EndpointDependant: - endpoint_dependencies: List["EndpointDependant"] = field(default_factory=list) - lifespan_dependencies: List[LifespanDependant] = field(default_factory=list) - name: Optional[str] = None - call: Optional[Callable[..., Any]] = None - use_cache: bool = True - index: Optional[int] = None - cache_key: Tuple[Optional[Callable[..., Any]], Tuple[str, ...]] = field(init=False) path_params: List[ModelField] = field(default_factory=list) query_params: List[ModelField] = field(default_factory=list) header_params: List[ModelField] = field(default_factory=list) cookie_params: List[ModelField] = field(default_factory=list) body_params: List[ModelField] = field(default_factory=list) + endpoint_dependencies: List["EndpointDependant"] = field(default_factory=list) + lifespan_dependencies: List[LifespanDependant] = field(default_factory=list) security_requirements: List[SecurityRequirement] = field(default_factory=list) + name: Optional[str] = None + call: Optional[Callable[..., Any]] = None + index: Optional[int] = None request_param_name: Optional[str] = None websocket_param_name: Optional[str] = None http_connection_param_name: Optional[str] = None @@ -66,10 +85,48 @@ class EndpointDependant: background_tasks_param_name: Optional[str] = None security_scopes_param_name: Optional[str] = None security_scopes: Optional[List[str]] = None + use_cache: bool = True path: Optional[str] = None + scope: Union[Literal["function", "request"], None] = None + + @cached_property + def cache_key(self) -> EndpointDependencyCacheKey: + return ( + self.call, + tuple(sorted(set(self.security_scopes or []))), + self.computed_scope or "", + ) - def __post_init__(self) -> None: - self.cache_key = (self.call, tuple(sorted(set(self.security_scopes or [])))) + @cached_property + def is_gen_callable(self) -> bool: + if inspect.isgeneratorfunction(self.call): + return True + dunder_call = getattr(self.call, "__call__", None) # noqa: B004 + return inspect.isgeneratorfunction(dunder_call) + + @cached_property + def is_async_gen_callable(self) -> bool: + if inspect.isasyncgenfunction(self.call): + return True + dunder_call = getattr(self.call, "__call__", None) # noqa: B004 + return inspect.isasyncgenfunction(dunder_call) + + @cached_property + def is_coroutine_callable(self) -> bool: + if inspect.isroutine(self.call): + return iscoroutinefunction(self.call) + if inspect.isclass(self.call): + return False + dunder_call = getattr(self.call, "__call__", None) # noqa: B004 + return iscoroutinefunction(dunder_call) + + @cached_property + def computed_scope(self) -> Union[str, None]: + if self.scope: + return self.scope + if self.is_gen_callable or self.is_async_gen_callable: + return "request" + return None # Kept for backwards compatibility @property @@ -87,5 +144,4 @@ class EndpointDependant: # Kept for backwards compatibility -Dependant = EndpointDependant -CacheKey: TypeAlias = Union[EndpointDependantCacheKey, LifespanDependantCacheKey] +Dependant: TypeAlias = EndpointDependant diff --git a/fastapi/dependencies/utils.py b/fastapi/dependencies/utils.py index 56c178c76..a58f24f56 100644 --- a/fastapi/dependencies/utils.py +++ b/fastapi/dependencies/utils.py @@ -1,5 +1,4 @@ import inspect -import sys from contextlib import AsyncExitStack, contextmanager from copy import copy, deepcopy from dataclasses import dataclass @@ -43,9 +42,9 @@ from fastapi._compat import ( is_uploadfile_or_nonable_uploadfile_annotation, is_uploadfile_sequence_annotation, lenient_issubclass, + may_v1, sequence_types, serialize_sequence_value, - v1, value_is_sequence, ) from fastapi._compat.shared import annotation_is_pydantic_v1 @@ -54,23 +53,13 @@ from fastapi.concurrency import ( asynccontextmanager, contextmanager_in_threadpool, ) -from fastapi.dependencies.models import ( - CacheKey, - EndpointDependant, - EndpointDependantCacheKey, - LifespanDependant, - LifespanDependantCacheKey, - SecurityRequirement, -) -from fastapi.exceptions import ( - DependencyScopeConflict, - 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 from fastapi.security.open_id_connect_url import OpenIdConnect +from fastapi.types import EndpointDependencyCacheKey, LifespanDependencyCacheKey from fastapi.utils import create_model_field, get_path_param_names from pydantic import BaseModel from pydantic.fields import FieldInfo @@ -86,15 +75,10 @@ from starlette.datastructures import ( from starlette.requests import HTTPConnection, Request from starlette.responses import Response from starlette.websockets import WebSocket -from typing_extensions import Annotated, get_args, get_origin +from typing_extensions import Annotated, Literal, get_args, get_origin from .. import temp_pydantic_v1_params -if sys.version_info >= (3, 13): # pragma: no cover - from inspect import iscoroutinefunction -else: # pragma: no cover - from asyncio import iscoroutinefunction - multipart_not_installed_error = ( 'Form data requires "python-multipart" to be installed. \n' 'You can install "python-multipart" with: \n\n' @@ -137,86 +121,33 @@ def ensure_multipart_is_installed() -> None: raise RuntimeError(multipart_not_installed_error) from None -def get_param_sub_dependant( - *, - param_name: str, - depends: params.Depends, - path: str, - caller: Callable[..., Any], - security_scopes: Optional[List[str]] = None, -) -> Union[EndpointDependant, LifespanDependant]: - assert depends.dependency - return get_sub_dependant( - depends=depends, - dependency=depends.dependency, - path=path, - name=param_name, - security_scopes=security_scopes, - caller=caller, - ) - - 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" ) - return get_sub_dependant( - depends=depends, - dependency=depends.dependency, - path=path, - caller=caller, - index=index, - ) - - -def get_sub_dependant( - *, - depends: params.Depends, - dependency: Callable[..., Any], - path: str, - caller: Callable[..., Any], - name: Optional[str] = None, - security_scopes: Optional[List[str]] = None, - index: Optional[int] = None, -) -> Union[EndpointDependant, LifespanDependant]: - if depends.dependency_scope == "lifespan": + if depends.scope in ("request", "function", None): + use_security_scopes: List[str] = [] + if isinstance(depends, params.Security) and depends.scopes: + use_security_scopes.extend(depends.scopes) + return get_endpoint_dependant( + path=path, + call=depends.dependency, + security_scopes=use_security_scopes, + index=index + ) + elif depends.scope == "lifespan": return get_lifespan_dependant( caller=caller, - call=dependency, - name=name, + call=depends.dependency, use_cache=depends.use_cache, index=index, ) - elif depends.dependency_scope == "endpoint": - security_requirement = None - security_scopes = security_scopes or [] - if isinstance(depends, params.Security): - dependency_scopes = depends.scopes - security_scopes.extend(dependency_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_endpoint_dependant( - path=path, - call=dependency, - name=name, - security_scopes=security_scopes, - use_cache=depends.use_cache, - index=index, - ) - if security_requirement: - sub_dependant.security_requirements.append(security_requirement) - return sub_dependant else: raise InvalidDependencyScope( - f'Dependency "{name}" of {caller} has an invalid ' - f'scope: "{depends.dependency_scope}"' + f'Dependency "{index}" of {caller} has an invalid ' + f'scope: "{depends.scope}"' ) @@ -224,7 +155,7 @@ def get_flat_dependant( dependant: EndpointDependant, *, skip_repeats: bool = False, - visited: Optional[List[CacheKey]] = None, + visited: Optional[List[EndpointDependencyCacheKey]] = None, ) -> EndpointDependant: if visited is None: visited = [] @@ -333,20 +264,18 @@ def get_lifespan_dependant( is_path_param=False, ) if param_details.depends is None: - raise DependencyScopeConflict( - f'Lifespan scoped dependency "{dependant.name}" was defined ' + raise DependencyScopeError( + f'Dependency "{dependant.name}" has "lifespan" scope, but was defined' f'with an invalid argument: "{param_name}" which is ' - f'"endpoint" scoped. Lifespan scoped dependencies may only ' + f'not a valid sub-dependency. Lifespan scoped dependencies may only ' f"use lifespan scoped sub-dependencies." ) - if param_details.depends.dependency_scope != "lifespan": - raise DependencyScopeConflict( - f"Lifespan scoped dependency {dependant.name} was defined with the " - f'sub-dependency "{param_name}" which is ' - f'"{param_details.depends.dependency_scope}" scoped. ' - f"Lifespan scoped dependencies may only use lifespan scoped " - f"sub-dependencies." + if param_details.depends.scope != "lifespan": + 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.' ) assert param_details.depends.dependency is not None @@ -370,18 +299,28 @@ def get_endpoint_dependant( security_scopes: Optional[List[str]] = None, use_cache: bool = True, index: Optional[int] = None, + scope: Union[Literal["function", "request"], None] = None, ) -> EndpointDependant: - path_param_names = get_path_param_names(path) - endpoint_signature = get_typed_signature(call) - signature_params = endpoint_signature.parameters dependant = EndpointDependant( call=call, name=name, path=path, security_scopes=security_scopes, use_cache=use_cache, + scope=scope, index=index, ) + path_param_names = get_path_param_names(path) + endpoint_signature = get_typed_signature(call) + signature_params = endpoint_signature.parameters + if isinstance(call, SecurityBase): + use_scopes: List[str] = [] + if isinstance(call, (OAuth2, OpenIdConnect)): + use_scopes = security_scopes or use_scopes + security_requirement = SecurityRequirement( + security_scheme=call, scopes=use_scopes + ) + dependant.security_requirements.append(security_requirement) for param_name, param in signature_params.items(): is_path_param = param_name in path_param_names param_details = analyze_param( @@ -391,18 +330,45 @@ def get_endpoint_dependant( is_path_param=is_path_param, ) if param_details.depends is not None: - sub_dependant = get_param_sub_dependant( - param_name=param_name, - depends=param_details.depends, - path=path, - security_scopes=security_scopes, - caller=call, - ) - if isinstance(sub_dependant, EndpointDependant): - dependant.endpoint_dependencies.append(sub_dependant) + assert param_details.depends.dependency + if ( + (dependant.is_gen_callable or dependant.is_async_gen_callable) + and dependant.computed_scope == "request" + and param_details.depends.scope == "function" + ): + assert dependant.call + raise DependencyScopeError( + f'The dependency "{dependant.call.__name__}" has a scope of ' + '"request", it cannot depend on dependencies with scope "function".' + ) + 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) + 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 + )) + 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 + )) else: - assert isinstance(sub_dependant, LifespanDependant) - dependant.lifespan_dependencies.append(sub_dependant) + raise InvalidDependencyScope( + f'Dependency "{name}" of {call} has an invalid ' + f'scope: "{param_details.depends.scope}"' + ) + continue if add_non_field_param_to_dependency( param_name=param_name, @@ -479,7 +445,7 @@ def analyze_param( fastapi_annotations = [ arg for arg in annotated_args[1:] - if isinstance(arg, (FieldInfo, v1.FieldInfo, params.Depends)) + if isinstance(arg, (FieldInfo, may_v1.FieldInfo, params.Depends)) ] fastapi_specific_annotations = [ arg @@ -496,21 +462,21 @@ def analyze_param( ) ] if fastapi_specific_annotations: - fastapi_annotation: Union[FieldInfo, v1.FieldInfo, params.Depends, None] = ( - fastapi_specific_annotations[-1] - ) + fastapi_annotation: Union[ + FieldInfo, may_v1.FieldInfo, params.Depends, None + ] = fastapi_specific_annotations[-1] else: fastapi_annotation = None # Set default for Annotated FieldInfo - if isinstance(fastapi_annotation, (FieldInfo, v1.FieldInfo)): + if isinstance(fastapi_annotation, (FieldInfo, may_v1.FieldInfo)): # Copy `field_info` because we mutate `field_info.default` below. field_info = copy_field_info( field_info=fastapi_annotation, annotation=use_annotation ) assert field_info.default in { Undefined, - v1.Undefined, - } or field_info.default in {RequiredParam, v1.RequiredParam}, ( + may_v1.Undefined, + } or field_info.default in {RequiredParam, may_v1.RequiredParam}, ( f"`{field_info.__class__.__name__}` default value cannot be set in" f" `Annotated` for {param_name!r}. Set the default value with `=` instead." ) @@ -534,7 +500,7 @@ def analyze_param( ) depends = value # Get FieldInfo from default value - elif isinstance(value, (FieldInfo, v1.FieldInfo)): + elif isinstance(value, (FieldInfo, may_v1.FieldInfo)): assert field_info is None, ( "Cannot specify FastAPI annotations in `Annotated` and default value" f" together for {param_name!r}" @@ -623,7 +589,8 @@ def analyze_param( type_=use_annotation_from_field_info, default=field_info.default, alias=alias, - required=field_info.default in (RequiredParam, v1.RequiredParam, Undefined), + required=field_info.default + in (RequiredParam, may_v1.RequiredParam, Undefined), field_info=field_info, ) if is_path_param: @@ -660,50 +627,28 @@ def add_param_to_fields(*, field: ModelField, dependant: EndpointDependant) -> N dependant.cookie_params.append(field) -def is_coroutine_callable(call: Callable[..., Any]) -> bool: - if inspect.isroutine(call): - return iscoroutinefunction(call) - if inspect.isclass(call): - return False - dunder_call = getattr(call, "__call__", None) # noqa: B004 - return iscoroutinefunction(dunder_call) - - -def is_async_gen_callable(call: Callable[..., Any]) -> bool: - if inspect.isasyncgenfunction(call): - return True - dunder_call = getattr(call, "__call__", None) # noqa: B004 - return inspect.isasyncgenfunction(dunder_call) - - -def is_gen_callable(call: Callable[..., Any]) -> bool: - if inspect.isgeneratorfunction(call): - return True - dunder_call = getattr(call, "__call__", None) # noqa: B004 - return inspect.isgeneratorfunction(dunder_call) - - -async def solve_generator( - *, call: Callable[..., Any], stack: AsyncExitStack, sub_values: Dict[str, Any] +async def _solve_generator( + *, dependant: Union[EndpointDependant, LifespanDependant], stack: AsyncExitStack, sub_values: Dict[str, Any] ) -> Any: - if is_gen_callable(call): - cm = contextmanager_in_threadpool(contextmanager(call)(**sub_values)) - elif is_async_gen_callable(call): - cm = asynccontextmanager(call)(**sub_values) + assert dependant.call + if dependant.is_gen_callable: + cm = contextmanager_in_threadpool(contextmanager(dependant.call)(**sub_values)) + elif dependant.is_async_gen_callable: + cm = asynccontextmanager(dependant.call)(**sub_values) return await stack.enter_async_context(cm) @dataclass class SolvedLifespanDependant: value: Any - dependency_cache: Dict[LifespanDependantCacheKey, Any] + dependency_cache: Dict[LifespanDependencyCacheKey, Any] async def solve_lifespan_dependant( *, dependant: LifespanDependant, dependency_overrides_provider: Optional[Any] = None, - dependency_cache: Dict[LifespanDependantCacheKey, Callable[..., Any]], + dependency_cache: Dict[LifespanDependencyCacheKey, Callable[..., Any]], async_exit_stack: AsyncExitStack, ) -> SolvedLifespanDependant: if dependant.use_cache and dependant.cache_key in dependency_cache: @@ -743,11 +688,11 @@ async def solve_lifespan_dependant( ) dependency_arguments[sub_dependant.name] = solved_sub_dependant.value - if is_gen_callable(call) or is_async_gen_callable(call): - value = await solve_generator( - call=call, stack=async_exit_stack, sub_values=dependency_arguments + 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 ) - elif is_coroutine_callable(call): + elif dependant_to_solve.is_coroutine_callable: value = await call(**dependency_arguments) else: value = await run_in_threadpool(call, **dependency_arguments) @@ -767,7 +712,7 @@ class SolvedDependency: errors: List[Any] background_tasks: Optional[StarletteBackgroundTasks] response: Response - dependency_cache: Dict[EndpointDependantCacheKey, Any] + dependency_cache: Dict[EndpointDependencyCacheKey, Any] async def solve_dependencies( @@ -778,10 +723,20 @@ async def solve_dependencies( background_tasks: Optional[StarletteBackgroundTasks] = None, response: Optional[Response] = None, dependency_overrides_provider: Optional[Any] = None, - dependency_cache: Optional[Dict[EndpointDependantCacheKey, Any]] = None, + dependency_cache: Optional[Dict[EndpointDependencyCacheKey, Any]] = None, + # TODO: remove this parameter later, no longer used, not removing it yet as some + # people might be monkey patching this function (although that's not supported) async_exit_stack: AsyncExitStack, embed_body_fields: bool, ) -> SolvedDependency: + request_astack = request.scope.get("fastapi_inner_astack") + assert isinstance(request_astack, AsyncExitStack), ( + "fastapi_inner_astack not found in request scope" + ) + function_astack = request.scope.get("fastapi_function_astack") + assert isinstance(function_astack, AsyncExitStack), ( + "fastapi_function_astack not found in request scope" + ) values: Dict[str, Any] = {} errors: List[Any] = [] @@ -818,12 +773,8 @@ async def solve_dependencies( response.status_code = None # type: ignore if dependency_cache is None: dependency_cache = {} - sub_dependant: EndpointDependant for sub_dependant in dependant.endpoint_dependencies: sub_dependant.call = cast(Callable[..., Any], sub_dependant.call) - sub_dependant.cache_key = cast( - Tuple[Callable[..., Any], Tuple[str]], sub_dependant.cache_key - ) call = sub_dependant.call use_sub_dependant = sub_dependant if ( @@ -840,6 +791,7 @@ async def solve_dependencies( call=call, name=sub_dependant.name, security_scopes=sub_dependant.security_scopes, + scope=sub_dependant.scope, ) solved_result = await solve_dependencies( @@ -859,11 +811,18 @@ async def solve_dependencies( continue if sub_dependant.use_cache and sub_dependant.cache_key in dependency_cache: solved = dependency_cache[sub_dependant.cache_key] - elif is_gen_callable(call) or is_async_gen_callable(call): - solved = await solve_generator( - call=call, stack=async_exit_stack, sub_values=solved_result.values + elif ( + use_sub_dependant.is_gen_callable or use_sub_dependant.is_async_gen_callable + ): + use_astack = request_astack + if sub_dependant.scope == "function": + use_astack = function_astack + solved = await _solve_generator( + dependant=use_sub_dependant, + stack=use_astack, + sub_values=solved_result.values, ) - elif is_coroutine_callable(call): + elif use_sub_dependant.is_coroutine_callable: solved = await call(**solved_result.values) else: solved = await run_in_threadpool(call, **solved_result.values) @@ -936,7 +895,7 @@ def _validate_value_with_model_field( if _is_error_wrapper(errors_): # type: ignore[arg-type] return None, [errors_] elif isinstance(errors_, list): - new_errors = v1._regenerate_error_with_loc(errors=errors_, loc_prefix=()) + new_errors = may_v1._regenerate_error_with_loc(errors=errors_, loc_prefix=()) return None, new_errors else: return v_, [] diff --git a/fastapi/encoders.py b/fastapi/encoders.py index 8ff7d58dd..6fc6228e1 100644 --- a/fastapi/encoders.py +++ b/fastapi/encoders.py @@ -17,13 +17,14 @@ from types import GeneratorType from typing import Any, Callable, Dict, List, Optional, Tuple, Type, Union from uuid import UUID -from fastapi._compat import v1 +from annotated_doc import Doc +from fastapi._compat import may_v1 from fastapi.types import IncEx from pydantic import BaseModel from pydantic.color import Color from pydantic.networks import AnyUrl, NameEmail from pydantic.types import SecretBytes, SecretStr -from typing_extensions import Annotated, Doc +from typing_extensions import Annotated from ._compat import Url, _is_undefined, _model_dump @@ -59,7 +60,7 @@ def decimal_encoder(dec_value: Decimal) -> Union[int, float]: ENCODERS_BY_TYPE: Dict[Type[Any], Callable[[Any], Any]] = { bytes: lambda o: o.decode(), Color: str, - v1.Color: str, + may_v1.Color: str, datetime.date: isoformat, datetime.datetime: isoformat, datetime.time: isoformat, @@ -76,19 +77,19 @@ ENCODERS_BY_TYPE: Dict[Type[Any], Callable[[Any], Any]] = { IPv6Interface: str, IPv6Network: str, NameEmail: str, - v1.NameEmail: str, + may_v1.NameEmail: str, Path: str, Pattern: lambda o: o.pattern, SecretBytes: str, - v1.SecretBytes: str, + may_v1.SecretBytes: str, SecretStr: str, - v1.SecretStr: str, + may_v1.SecretStr: str, set: list, UUID: str, Url: str, - v1.Url: str, + may_v1.Url: str, AnyUrl: str, - v1.AnyUrl: str, + may_v1.AnyUrl: str, } @@ -220,10 +221,10 @@ def jsonable_encoder( include = set(include) if exclude is not None and not isinstance(exclude, (set, dict)): exclude = set(exclude) - if isinstance(obj, (BaseModel, v1.BaseModel)): + if isinstance(obj, (BaseModel, may_v1.BaseModel)): # TODO: remove when deprecating Pydantic v1 encoders: Dict[Any, Any] = {} - if isinstance(obj, v1.BaseModel): + if isinstance(obj, may_v1.BaseModel): encoders = getattr(obj.__config__, "json_encoders", {}) # type: ignore[attr-defined] if custom_encoder: encoders = {**encoders, **custom_encoder} diff --git a/fastapi/exceptions.py b/fastapi/exceptions.py index 95fd60477..01b9bbe44 100644 --- a/fastapi/exceptions.py +++ b/fastapi/exceptions.py @@ -1,9 +1,10 @@ from typing import Any, Dict, Optional, Sequence, Type, Union +from annotated_doc import Doc from pydantic import BaseModel, create_model from starlette.exceptions import HTTPException as StarletteHTTPException from starlette.exceptions import WebSocketException as StarletteWebSocketException -from typing_extensions import Annotated, Doc +from typing_extensions import Annotated class HTTPException(StarletteHTTPException): @@ -145,23 +146,31 @@ 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 DependencyScopeConflict(DependencyError): - 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 diff --git a/fastapi/lifespan.py b/fastapi/lifespan.py index 7d53fc00a..4f5a20a4f 100644 --- a/fastapi/lifespan.py +++ b/fastapi/lifespan.py @@ -3,7 +3,7 @@ from __future__ import annotations from contextlib import AsyncExitStack from typing import TYPE_CHECKING, Any, Callable, Dict, List -from fastapi.dependencies.models import LifespanDependant, LifespanDependantCacheKey +from fastapi.dependencies.models import LifespanDependant, LifespanDependencyCacheKey from fastapi.dependencies.utils import solve_lifespan_dependant from fastapi.routing import APIRoute, APIWebSocketRoute @@ -12,7 +12,7 @@ if TYPE_CHECKING: # pragma: nocover def _get_lifespan_dependants(app: FastAPI) -> List[LifespanDependant]: - lifespan_dependants_cache: Dict[LifespanDependantCacheKey, LifespanDependant] = {} + lifespan_dependants_cache: Dict[LifespanDependencyCacheKey, LifespanDependant] = {} for route in app.router.routes: if not isinstance(route, (APIWebSocketRoute, APIRoute)): continue @@ -28,9 +28,9 @@ def _get_lifespan_dependants(app: FastAPI) -> List[LifespanDependant]: async def resolve_lifespan_dependants( *, app: FastAPI, async_exit_stack: AsyncExitStack -) -> Dict[LifespanDependantCacheKey, Callable[..., Any]]: +) -> Dict[LifespanDependencyCacheKey, Callable[..., Any]]: lifespan_dependants = _get_lifespan_dependants(app) - dependency_cache: Dict[LifespanDependantCacheKey, Callable[..., Any]] = {} + dependency_cache: Dict[LifespanDependencyCacheKey, Callable[..., Any]] = {} for lifespan_dependant in lifespan_dependants: solved_dependency = await solve_lifespan_dependant( dependant=lifespan_dependant, diff --git a/fastapi/openapi/docs.py b/fastapi/openapi/docs.py index f181b43c1..74b23a370 100644 --- a/fastapi/openapi/docs.py +++ b/fastapi/openapi/docs.py @@ -1,9 +1,10 @@ import json from typing import Any, Dict, Optional +from annotated_doc import Doc from fastapi.encoders import jsonable_encoder from starlette.responses import HTMLResponse -from typing_extensions import Annotated, Doc +from typing_extensions import Annotated swagger_ui_default_parameters: Annotated[ Dict[str, Any], diff --git a/fastapi/param_functions.py b/fastapi/param_functions.py index 4112e90e2..5838c1bd5 100644 --- a/fastapi/param_functions.py +++ b/fastapi/param_functions.py @@ -1,12 +1,10 @@ -from __future__ import annotations - from typing import Any, Callable, Dict, List, Optional, Sequence, Union +from annotated_doc import Doc from fastapi import params from fastapi._compat import Undefined from fastapi.openapi.models import Example -from fastapi.params import DependencyScope -from typing_extensions import Annotated, Doc, deprecated +from typing_extensions import Annotated, Literal, deprecated _Unset: Any = Undefined @@ -2247,33 +2245,28 @@ def Depends( # noqa: N802 """ ), ] = True, - dependency_scope: Annotated[ - DependencyScope, + scope: Annotated[ + Union[Literal["function", "request", "lifespan"], None], Doc( """ - The scope in which the dependency value should be evaluated. Can be - either `"endpoint"` or `"lifespan"`. - - If `dependency_scope` is set to "endpoint" (the default), the - dependency will be setup and teardown for every request. - - If `dependency_scope` is set to `"lifespan"` the dependency would - be setup at the start of the entire application's lifespan. The - evaluated dependency would be then reused across all endpoints. - The dependency would be teared down as a part of the application's - shutdown process. + Mainly for dependencies with `yield`, define when the dependency function + should start (the code before `yield`) and when it should end (the code + after `yield`). - Note that dependencies defined with the `"endpoint"` scope may use - sub-dependencies defined with the `"lifespan"` scope, but not the - other way around; - Dependencies defined with the `"lifespan"` scope may not use - sub-dependencies with `"endpoint"` scope, nor can they use - other "endpoint scoped" arguments such as "Path", "Body", "Query", - or any other annotation which does not make sense in a scope of an - application's entire lifespan. + * `"function"`: start the dependency before the *path operation function* + that handles the request, end the dependency after the *path operation + function* ends, but **before** the response is sent back to the client. + So, the dependency function will be executed **around** the *path operation + **function***. + * `"request"`: start the dependency before the *path operation function* + that handles the request (similar to when using `"function"`), but end + **after** the response is sent back to the client. So, the dependency + function will be executed **around** the **request** and response cycle. + * `"lifespan"`: start the dependency when the FastAPI application starts, + end the dependency during the FastAPI application shuts down. """ ), - ] = "endpoint", + ] = None, ) -> Any: """ Declare a FastAPI dependency. @@ -2304,9 +2297,7 @@ def Depends( # noqa: N802 return commons ``` """ - return params.Depends( - dependency=dependency, use_cache=use_cache, dependency_scope=dependency_scope - ) + return params.Depends(dependency=dependency, use_cache=use_cache, scope=scope) def Security( # noqa: N802 diff --git a/fastapi/params.py b/fastapi/params.py index 28d6e67cb..96bd67024 100644 --- a/fastapi/params.py +++ b/fastapi/params.py @@ -1,4 +1,5 @@ import warnings +from dataclasses import dataclass from enum import Enum from typing import Any, Callable, Dict, List, Optional, Sequence, Union @@ -11,9 +12,11 @@ from ._compat import ( PYDANTIC_VERSION_MINOR_TUPLE, Undefined, ) +from .exceptions import InvalidDependencyScope _Unset: Any = Undefined -DependencyScope: TypeAlias = Literal["endpoint", "lifespan"] +_EndpointDependencyScope: TypeAlias = Literal["request", "function"] +DependencyScope: TypeAlias = Union[Literal["lifespan"], _EndpointDependencyScope] class ParamTypes(Enum): @@ -762,38 +765,18 @@ class File(Form): # type: ignore[misc] ) +@dataclass class Depends: - def __init__( - self, - dependency: Optional[Callable[..., Any]] = None, - *, - use_cache: bool = True, - dependency_scope: DependencyScope = "endpoint", - ): - self.dependency = dependency - self.use_cache = use_cache - self.dependency_scope = dependency_scope - - def __repr__(self) -> str: - attr = getattr(self.dependency, "__name__", type(self.dependency).__name__) - cache = "" if self.use_cache else ", use_cache=False" - if self.dependency_scope == "endpoint": - dependency_scope = "" - else: - dependency_scope = f', dependency_scope="{self.dependency_scope}"' + dependency: Optional[Callable[..., Any]] = None + use_cache: bool = True + scope: Union[DependencyScope, None] = None - return f"{self.__class__.__name__}({attr}{cache}{dependency_scope})" + def __post_init__(self): + if self.scope not in ("lifespan", "request", "function", None): + raise InvalidDependencyScope(f"Dependency received an invalid scope: \"{self.scope}\"") +@dataclass class Security(Depends): - def __init__( - self, - dependency: Optional[Callable[..., Any]] = None, - *, - scopes: Optional[Sequence[str]] = None, - use_cache: bool = True, - ): - super().__init__( - dependency=dependency, use_cache=use_cache, dependency_scope="endpoint" - ) - self.scopes = scopes or [] + scope: Union[_EndpointDependencyScope, None] = None + scopes: Optional[Sequence[str]] = None diff --git a/fastapi/routing.py b/fastapi/routing.py index 9803699bb..fc3f4aaa9 100644 --- a/fastapi/routing.py +++ b/fastapi/routing.py @@ -24,6 +24,7 @@ from typing import ( Union, ) +from annotated_doc import Doc from fastapi import params, temp_pydantic_v1_params from fastapi._compat import ( ModelField, @@ -76,7 +77,7 @@ from starlette.routing import ( from starlette.routing import Mount as Mount # noqa from starlette.types import AppType, ASGIApp, Lifespan, Receive, Scope, Send from starlette.websockets import WebSocket -from typing_extensions import Annotated, Doc, deprecated +from typing_extensions import Annotated, deprecated if sys.version_info >= (3, 13): # pragma: no cover from inspect import iscoroutinefunction @@ -103,10 +104,11 @@ def request_response( async def app(scope: Scope, receive: Receive, send: Send) -> None: # Starts customization response_awaited = False - async with AsyncExitStack() as stack: - scope["fastapi_inner_astack"] = stack - # Same as in Starlette - response = await f(request) + async with AsyncExitStack() as request_stack: + scope["fastapi_inner_astack"] = request_stack + async with AsyncExitStack() as function_stack: + scope["fastapi_function_astack"] = function_stack + response = await f(request) await response(scope, receive, send) # Continues customization response_awaited = True @@ -139,11 +141,11 @@ def websocket_session( session = WebSocket(scope, receive=receive, send=send) async def app(scope: Scope, receive: Receive, send: Send) -> None: - # Starts customization - async with AsyncExitStack() as stack: - scope["fastapi_inner_astack"] = stack - # Same as in Starlette - await func(session) + async with AsyncExitStack() as request_stack: + scope["fastapi_inner_astack"] = request_stack + async with AsyncExitStack() as function_stack: + scope["fastapi_function_astack"] = function_stack + await func(session) # Same as in Starlette await wrap_app_handling_exceptions(app, session)(scope, receive, send) @@ -479,7 +481,7 @@ class APIWebSocketRoute(routing.WebSocketRoute): self.dependencies = list(dependencies or []) self.path_regex, self.path_format, self.param_convertors = compile_path(path) self.dependant = get_endpoint_dependant( - path=self.path_format, call=self.endpoint + path=self.path_format, call=self.endpoint, scope="function" ) for i, depends in list(enumerate(self.dependencies))[::-1]: sub_dependant = get_parameterless_sub_dependant( @@ -642,7 +644,7 @@ class APIRoute(routing.Route): assert callable(endpoint), "An endpoint must be a callable" self.dependant = get_endpoint_dependant( - path=self.path_format, call=self.endpoint + path=self.path_format, call=self.endpoint, scope="function" ) for i, depends in list(enumerate(self.dependencies))[::-1]: sub_dependant = get_parameterless_sub_dependant( diff --git a/fastapi/security/api_key.py b/fastapi/security/api_key.py index 6d6dd01d9..496c815a7 100644 --- a/fastapi/security/api_key.py +++ b/fastapi/security/api_key.py @@ -1,11 +1,12 @@ from typing import Optional +from annotated_doc import Doc from fastapi.openapi.models import APIKey, APIKeyIn from fastapi.security.base import SecurityBase from starlette.exceptions import HTTPException from starlette.requests import Request from starlette.status import HTTP_403_FORBIDDEN -from typing_extensions import Annotated, Doc +from typing_extensions import Annotated class APIKeyBase(SecurityBase): diff --git a/fastapi/security/http.py b/fastapi/security/http.py index 9ab2df3c9..3a5985650 100644 --- a/fastapi/security/http.py +++ b/fastapi/security/http.py @@ -2,6 +2,7 @@ import binascii from base64 import b64decode from typing import Optional +from annotated_doc import Doc from fastapi.exceptions import HTTPException from fastapi.openapi.models import HTTPBase as HTTPBaseModel from fastapi.openapi.models import HTTPBearer as HTTPBearerModel @@ -10,7 +11,7 @@ from fastapi.security.utils import get_authorization_scheme_param from pydantic import BaseModel from starlette.requests import Request from starlette.status import HTTP_401_UNAUTHORIZED, HTTP_403_FORBIDDEN -from typing_extensions import Annotated, Doc +from typing_extensions import Annotated class HTTPBasicCredentials(BaseModel): diff --git a/fastapi/security/oauth2.py b/fastapi/security/oauth2.py index fdedbc2da..f8d97d762 100644 --- a/fastapi/security/oauth2.py +++ b/fastapi/security/oauth2.py @@ -1,5 +1,6 @@ from typing import Any, Dict, List, Optional, Union, cast +from annotated_doc import Doc from fastapi.exceptions import HTTPException from fastapi.openapi.models import OAuth2 as OAuth2Model from fastapi.openapi.models import OAuthFlows as OAuthFlowsModel @@ -10,7 +11,7 @@ from starlette.requests import Request from starlette.status import HTTP_401_UNAUTHORIZED, HTTP_403_FORBIDDEN # TODO: import from typing when deprecating Python 3.9 -from typing_extensions import Annotated, Doc +from typing_extensions import Annotated class OAuth2PasswordRequestForm: diff --git a/fastapi/security/open_id_connect_url.py b/fastapi/security/open_id_connect_url.py index c8cceb911..5e99798e6 100644 --- a/fastapi/security/open_id_connect_url.py +++ b/fastapi/security/open_id_connect_url.py @@ -1,11 +1,12 @@ from typing import Optional +from annotated_doc import Doc from fastapi.openapi.models import OpenIdConnect as OpenIdConnectModel from fastapi.security.base import SecurityBase from starlette.exceptions import HTTPException from starlette.requests import Request from starlette.status import HTTP_403_FORBIDDEN -from typing_extensions import Annotated, Doc +from typing_extensions import Annotated class OpenIdConnect(SecurityBase): diff --git a/fastapi/temp_pydantic_v1_params.py b/fastapi/temp_pydantic_v1_params.py index 0535ee727..e41d71230 100644 --- a/fastapi/temp_pydantic_v1_params.py +++ b/fastapi/temp_pydantic_v1_params.py @@ -5,8 +5,8 @@ from fastapi.openapi.models import Example from fastapi.params import ParamTypes from typing_extensions import Annotated, deprecated +from ._compat.may_v1 import FieldInfo, Undefined from ._compat.shared import PYDANTIC_VERSION_MINOR_TUPLE -from ._compat.v1 import FieldInfo, Undefined _Unset: Any = Undefined diff --git a/fastapi/types.py b/fastapi/types.py index 3205654c7..562f849a5 100644 --- a/fastapi/types.py +++ b/fastapi/types.py @@ -1,6 +1,6 @@ import types from enum import Enum -from typing import Any, Callable, Dict, Set, Type, TypeVar, Union +from typing import Any, Callable, Dict, Optional, Set, Tuple, Type, TypeVar, Union from pydantic import BaseModel @@ -8,3 +8,8 @@ DecoratedCallable = TypeVar("DecoratedCallable", bound=Callable[..., Any]) UnionType = getattr(types, "UnionType", Union) ModelNameMap = Dict[Union[Type[BaseModel], Type[Enum]], str] IncEx = Union[Set[int], Set[str], Dict[int, Any], Dict[str, Any]] + +LifespanDependencyCacheKey = Union[ + Tuple[Callable[..., Any], Union[str, int]], Callable[..., Any] +] +EndpointDependencyCacheKey = Tuple[Optional[Callable[..., Any]], Tuple[str, ...], str] diff --git a/fastapi/utils.py b/fastapi/utils.py index 3ea9271b1..8be10ff15 100644 --- a/fastapi/utils.py +++ b/fastapi/utils.py @@ -1,5 +1,8 @@ +import inspect import re +import sys import warnings +from collections.abc import Callable from dataclasses import is_dataclass from typing import ( TYPE_CHECKING, @@ -10,10 +13,12 @@ from typing import ( Set, Type, Union, - cast, + cast, Awaitable, TypeVar, ) from weakref import WeakKeyDictionary +from starlette.concurrency import run_in_threadpool + import fastapi from fastapi._compat import ( PYDANTIC_V2, @@ -25,16 +30,25 @@ from fastapi._compat import ( Validator, annotation_is_pydantic_v1, lenient_issubclass, - v1, + may_v1, ) from fastapi.datastructures import DefaultPlaceholder, DefaultType from pydantic import BaseModel from pydantic.fields import FieldInfo -from typing_extensions import Literal +from typing_extensions import Literal, TypeIs, ParamSpec if TYPE_CHECKING: # pragma: nocover from .routing import APIRoute +if sys.version_info >= (3, 13): # pragma: no cover + from inspect import iscoroutinefunction +else: # pragma: no cover + from asyncio import iscoroutinefunction + + +_T = TypeVar("_T") +_P = ParamSpec("_P") + # Cache for `create_cloned_field` _CLONED_TYPES_CACHE: MutableMapping[Type[BaseModel], Type[BaseModel]] = ( WeakKeyDictionary() @@ -87,8 +101,8 @@ def create_model_field( ) -> ModelField: class_validators = class_validators or {} - v1_model_config = v1.BaseConfig - v1_field_info = field_info or v1.FieldInfo() + v1_model_config = may_v1.BaseConfig + v1_field_info = field_info or may_v1.FieldInfo() v1_kwargs = { "name": name, "field_info": v1_field_info, @@ -102,9 +116,11 @@ def create_model_field( if ( annotation_is_pydantic_v1(type_) - or isinstance(field_info, v1.FieldInfo) + or isinstance(field_info, may_v1.FieldInfo) or version == "1" ): + from fastapi._compat import v1 + try: return v1.ModelField(**v1_kwargs) # type: ignore[no-any-return] except RuntimeError: @@ -122,6 +138,8 @@ def create_model_field( raise fastapi.exceptions.FastAPIError(_invalid_args_message) from None # Pydantic v2 is not installed, but it's not a Pydantic v1 ModelField, it could be # a Pydantic v1 type, like a constrained int + from fastapi._compat import v1 + try: return v1.ModelField(**v1_kwargs) # type: ignore[no-any-return] except RuntimeError: @@ -138,6 +156,9 @@ def create_cloned_field( if isinstance(field, v2.ModelField): return field + + from fastapi._compat import v1 + # cloned_types caches already cloned types to support recursive models and improve # performance by avoiding unnecessary cloning if cloned_types is None: @@ -245,3 +266,24 @@ def get_value_or_default( if not isinstance(item, DefaultPlaceholder): return item return first_item + + +def _is_coroutine_callable( + callable_: Callable[..., Any] +) -> TypeIs[Callable[..., Awaitable[Any]]]: + if inspect.isroutine(callable_): + return iscoroutinefunction(callable_) + if inspect.isclass(callable_): + return False + 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 +) -> _T: + if _is_coroutine_callable(callable_): + return await callable_(*args, **kwargs) + else: + return await run_in_threadpool(callable_, *args, **kwargs) \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index cac8059f4..7d2be0074 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -7,6 +7,8 @@ name = "fastapi" dynamic = ["version"] description = "FastAPI framework, high performance, easy to learn, fast to code, ready for production" readme = "README.md" +license = "MIT" +license-files = ["LICENSE"] requires-python = ">=3.8" authors = [ { name = "Sebastián Ramírez", email = "tiangolo@gmail.com" }, @@ -31,7 +33,6 @@ classifiers = [ "Framework :: Pydantic :: 1", "Framework :: Pydantic :: 2", "Intended Audience :: Developers", - "License :: OSI Approved :: MIT License", "Programming Language :: Python :: 3 :: Only", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", @@ -44,9 +45,10 @@ classifiers = [ "Topic :: Internet :: WWW/HTTP", ] dependencies = [ - "starlette>=0.40.0,<0.49.0", + "starlette>=0.40.0,<0.50.0", "pydantic>=1.7.4,!=1.8,!=1.8.1,!=2.0.0,!=2.0.1,!=2.1.0,<3.0.0", "typing-extensions>=4.8.0", + "annotated-doc>=0.0.2", ] [project.urls] diff --git a/requirements-docs-tests.txt b/requirements-docs-tests.txt index a909d0eef..9350f3ee4 100644 --- a/requirements-docs-tests.txt +++ b/requirements-docs-tests.txt @@ -1,4 +1,4 @@ # For mkdocstrings and tests httpx >=0.23.0,<1.0.0 # For linting and generating docs versions -ruff ==0.13.2 +ruff ==0.14.3 diff --git a/requirements-docs.txt b/requirements-docs.txt index 0013f9f79..696eb2a33 100644 --- a/requirements-docs.txt +++ b/requirements-docs.txt @@ -11,9 +11,9 @@ jieba==0.42.1 pillow==11.3.0 # For image processing by Material for MkDocs cairosvg==2.8.2 -mkdocstrings[python]==0.26.1 -griffe-typingdoc==0.2.9 +mkdocstrings[python]==0.30.1 +griffe-typingdoc==0.3.0 # For griffe, it formats with black black==25.1.0 -mkdocs-macros-plugin==1.4.0 +mkdocs-macros-plugin==1.4.1 markdown-include-variants==0.0.5 diff --git a/tests/test_compat.py b/tests/test_compat.py index f79dbdabc..0184c9a2e 100644 --- a/tests/test_compat.py +++ b/tests/test_compat.py @@ -7,7 +7,7 @@ from fastapi._compat import ( get_cached_model_fields, is_scalar_field, is_uploadfile_sequence_annotation, - v1, + may_v1, ) from fastapi._compat.shared import is_bytes_sequence_annotation from fastapi.testclient import TestClient @@ -27,7 +27,10 @@ def test_model_field_default_required(): assert field.default is Undefined +@needs_py_lt_314 def test_v1_plain_validator_function(): + from fastapi._compat import v1 + # For coverage def func(v): # pragma: no cover return v @@ -135,6 +138,8 @@ def test_is_uploadfile_sequence_annotation(): @needs_py_lt_314 def test_is_pv1_scalar_field(): + from fastapi._compat import v1 + # For coverage class Model(v1.BaseModel): foo: Union[str, Dict[str, Any]] @@ -143,8 +148,11 @@ def test_is_pv1_scalar_field(): assert not is_scalar_field(fields[0]) +@needs_py_lt_314 def test_get_model_fields_cached(): - class Model(v1.BaseModel): + from fastapi._compat import v1 + + class Model(may_v1.BaseModel): foo: str non_cached_fields = v1.get_model_fields(Model) diff --git a/tests/test_dependency_paramless.py b/tests/test_dependency_paramless.py new file mode 100644 index 000000000..9c3cc3878 --- /dev/null +++ b/tests/test_dependency_paramless.py @@ -0,0 +1,78 @@ +from typing import Union + +from fastapi import FastAPI, HTTPException, Security +from fastapi.security import ( + OAuth2PasswordBearer, + SecurityScopes, +) +from fastapi.testclient import TestClient +from typing_extensions import Annotated + +app = FastAPI() + +oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token") + + +def process_auth( + credentials: Annotated[Union[str, None], Security(oauth2_scheme)], + security_scopes: SecurityScopes, +): + # This is an incorrect way of using it, this is not checking if the scopes are + # provided by the token, only if the endpoint is requesting them, but the test + # here is just to check if FastAPI is indeed registering and passing the scopes + # correctly when using Security with parameterless dependencies. + if "a" not in security_scopes.scopes or "b" not in security_scopes.scopes: + raise HTTPException(detail="a or b not in scopes", status_code=401) + return {"token": credentials, "scopes": security_scopes.scopes} + + +@app.get("/get-credentials") +def get_credentials( + credentials: Annotated[dict, Security(process_auth, scopes=["a", "b"])], +): + return credentials + + +@app.get( + "/parameterless-with-scopes", + dependencies=[Security(process_auth, scopes=["a", "b"])], +) +def get_parameterless_with_scopes(): + return {"status": "ok"} + + +@app.get( + "/parameterless-without-scopes", + dependencies=[Security(process_auth)], +) +def get_parameterless_without_scopes(): + return {"status": "ok"} + + +client = TestClient(app) + + +def test_get_credentials(): + response = client.get("/get-credentials", headers={"authorization": "Bearer token"}) + assert response.status_code == 200, response.text + assert response.json() == {"token": "token", "scopes": ["a", "b"]} + + +def test_parameterless_with_scopes(): + response = client.get( + "/parameterless-with-scopes", headers={"authorization": "Bearer token"} + ) + assert response.status_code == 200, response.text + assert response.json() == {"status": "ok"} + + +def test_parameterless_without_scopes(): + response = client.get( + "/parameterless-without-scopes", headers={"authorization": "Bearer token"} + ) + assert response.status_code == 401, response.text + assert response.json() == {"detail": "a or b not in scopes"} + + +def test_call_get_parameterless_without_scopes_for_coverage(): + assert get_parameterless_without_scopes() == {"status": "ok"} diff --git a/tests/test_dependency_yield_scope.py b/tests/test_dependency_yield_scope.py new file mode 100644 index 000000000..a5227dd7a --- /dev/null +++ b/tests/test_dependency_yield_scope.py @@ -0,0 +1,184 @@ +import json +from typing import Any, Tuple + +import pytest +from fastapi import Depends, FastAPI +from fastapi.exceptions import FastAPIError +from fastapi.responses import StreamingResponse +from fastapi.testclient import TestClient +from typing_extensions import Annotated + + +class Session: + def __init__(self) -> None: + self.open = True + + +def dep_session() -> Any: + s = Session() + yield s + s.open = False + + +SessionFuncDep = Annotated[Session, Depends(dep_session, scope="function")] +SessionRequestDep = Annotated[Session, Depends(dep_session, scope="request")] +SessionDefaultDep = Annotated[Session, Depends(dep_session)] + + +class NamedSession: + def __init__(self, name: str = "default") -> None: + self.name = name + self.open = True + + +def get_named_session(session: SessionRequestDep, session_b: SessionDefaultDep) -> Any: + assert session is session_b + named_session = NamedSession(name="named") + yield named_session, session_b + named_session.open = False + + +NamedSessionsDep = Annotated[Tuple[NamedSession, Session], Depends(get_named_session)] + + +def get_named_func_session(session: SessionFuncDep) -> Any: + named_session = NamedSession(name="named") + yield named_session, session + named_session.open = False + + +def get_named_regular_func_session(session: SessionFuncDep) -> Any: + named_session = NamedSession(name="named") + return named_session, session + + +BrokenSessionsDep = Annotated[ + Tuple[NamedSession, Session], Depends(get_named_func_session) +] +NamedSessionsFuncDep = Annotated[ + Tuple[NamedSession, Session], Depends(get_named_func_session, scope="function") +] + +RegularSessionsDep = Annotated[ + Tuple[NamedSession, Session], Depends(get_named_regular_func_session) +] + +app = FastAPI() + + +@app.get("/function-scope") +def function_scope(session: SessionFuncDep) -> Any: + def iter_data(): + yield json.dumps({"is_open": session.open}) + + return StreamingResponse(iter_data()) + + +@app.get("/request-scope") +def request_scope(session: SessionRequestDep) -> Any: + def iter_data(): + yield json.dumps({"is_open": session.open}) + + return StreamingResponse(iter_data()) + + +@app.get("/two-scopes") +def get_stream_session( + function_session: SessionFuncDep, request_session: SessionRequestDep +) -> Any: + def iter_data(): + yield json.dumps( + {"func_is_open": function_session.open, "req_is_open": request_session.open} + ) + + return StreamingResponse(iter_data()) + + +@app.get("/sub") +def get_sub(sessions: NamedSessionsDep) -> Any: + def iter_data(): + yield json.dumps( + {"named_session_open": sessions[0].open, "session_open": sessions[1].open} + ) + + return StreamingResponse(iter_data()) + + +@app.get("/named-function-scope") +def get_named_function_scope(sessions: NamedSessionsFuncDep) -> Any: + def iter_data(): + yield json.dumps( + {"named_session_open": sessions[0].open, "session_open": sessions[1].open} + ) + + return StreamingResponse(iter_data()) + + +@app.get("/regular-function-scope") +def get_regular_function_scope(sessions: RegularSessionsDep) -> Any: + def iter_data(): + yield json.dumps( + {"named_session_open": sessions[0].open, "session_open": sessions[1].open} + ) + + return StreamingResponse(iter_data()) + + +client = TestClient(app) + + +def test_function_scope() -> None: + response = client.get("/function-scope") + assert response.status_code == 200 + data = response.json() + assert data["is_open"] is False + + +def test_request_scope() -> None: + response = client.get("/request-scope") + assert response.status_code == 200 + data = response.json() + assert data["is_open"] is True + + +def test_two_scopes() -> None: + response = client.get("/two-scopes") + assert response.status_code == 200 + data = response.json() + assert data["func_is_open"] is False + assert data["req_is_open"] is True + + +def test_sub() -> None: + response = client.get("/sub") + assert response.status_code == 200 + data = response.json() + assert data["named_session_open"] is True + assert data["session_open"] is True + + +def test_broken_scope() -> None: + with pytest.raises( + FastAPIError, + match='The dependency "get_named_func_session" has a scope of "request", it cannot depend on dependencies with scope "function"', + ): + + @app.get("/broken-scope") + def get_broken(sessions: BrokenSessionsDep) -> Any: # pragma: no cover + pass + + +def test_named_function_scope() -> None: + response = client.get("/named-function-scope") + assert response.status_code == 200 + data = response.json() + assert data["named_session_open"] is False + assert data["session_open"] is False + + +def test_regular_function_scope() -> None: + response = client.get("/regular-function-scope") + assert response.status_code == 200 + data = response.json() + assert data["named_session_open"] is True + assert data["session_open"] is False diff --git a/tests/test_dependency_yield_scope_websockets.py b/tests/test_dependency_yield_scope_websockets.py new file mode 100644 index 000000000..52a30ae7a --- /dev/null +++ b/tests/test_dependency_yield_scope_websockets.py @@ -0,0 +1,201 @@ +from contextvars import ContextVar +from typing import Any, Dict, Tuple + +import pytest +from fastapi import Depends, FastAPI, WebSocket +from fastapi.exceptions import FastAPIError +from fastapi.testclient import TestClient +from typing_extensions import Annotated + +global_context: ContextVar[Dict[str, Any]] = ContextVar("global_context", default={}) # noqa: B039 + + +class Session: + def __init__(self) -> None: + self.open = True + + +async def dep_session() -> Any: + s = Session() + yield s + s.open = False + global_state = global_context.get() + global_state["session_closed"] = True + + +SessionFuncDep = Annotated[Session, Depends(dep_session, scope="function")] +SessionRequestDep = Annotated[Session, Depends(dep_session, scope="request")] +SessionDefaultDep = Annotated[Session, Depends(dep_session)] + + +class NamedSession: + def __init__(self, name: str = "default") -> None: + self.name = name + self.open = True + + +def get_named_session(session: SessionRequestDep, session_b: SessionDefaultDep) -> Any: + assert session is session_b + named_session = NamedSession(name="named") + yield named_session, session_b + named_session.open = False + global_state = global_context.get() + global_state["named_session_closed"] = True + + +NamedSessionsDep = Annotated[Tuple[NamedSession, Session], Depends(get_named_session)] + + +def get_named_func_session(session: SessionFuncDep) -> Any: + named_session = NamedSession(name="named") + yield named_session, session + named_session.open = False + global_state = global_context.get() + global_state["named_func_session_closed"] = True + + +def get_named_regular_func_session(session: SessionFuncDep) -> Any: + named_session = NamedSession(name="named") + return named_session, session + + +BrokenSessionsDep = Annotated[ + Tuple[NamedSession, Session], Depends(get_named_func_session) +] +NamedSessionsFuncDep = Annotated[ + Tuple[NamedSession, Session], Depends(get_named_func_session, scope="function") +] + +RegularSessionsDep = Annotated[ + Tuple[NamedSession, Session], Depends(get_named_regular_func_session) +] + +app = FastAPI() + + +@app.websocket("/function-scope") +async def function_scope(websocket: WebSocket, session: SessionFuncDep) -> Any: + await websocket.accept() + await websocket.send_json({"is_open": session.open}) + + +@app.websocket("/request-scope") +async def request_scope(websocket: WebSocket, session: SessionRequestDep) -> Any: + await websocket.accept() + await websocket.send_json({"is_open": session.open}) + + +@app.websocket("/two-scopes") +async def get_stream_session( + websocket: WebSocket, + function_session: SessionFuncDep, + request_session: SessionRequestDep, +) -> Any: + await websocket.accept() + await websocket.send_json( + {"func_is_open": function_session.open, "req_is_open": request_session.open} + ) + + +@app.websocket("/sub") +async def get_sub(websocket: WebSocket, sessions: NamedSessionsDep) -> Any: + await websocket.accept() + await websocket.send_json( + {"named_session_open": sessions[0].open, "session_open": sessions[1].open} + ) + + +@app.websocket("/named-function-scope") +async def get_named_function_scope( + websocket: WebSocket, sessions: NamedSessionsFuncDep +) -> Any: + await websocket.accept() + await websocket.send_json( + {"named_session_open": sessions[0].open, "session_open": sessions[1].open} + ) + + +@app.websocket("/regular-function-scope") +async def get_regular_function_scope( + websocket: WebSocket, sessions: RegularSessionsDep +) -> Any: + await websocket.accept() + await websocket.send_json( + {"named_session_open": sessions[0].open, "session_open": sessions[1].open} + ) + + +client = TestClient(app) + + +def test_function_scope() -> None: + global_context.set({}) + global_state = global_context.get() + with client.websocket_connect("/function-scope") as websocket: + data = websocket.receive_json() + assert data["is_open"] is True + assert global_state["session_closed"] is True + + +def test_request_scope() -> None: + global_context.set({}) + global_state = global_context.get() + with client.websocket_connect("/request-scope") as websocket: + data = websocket.receive_json() + assert data["is_open"] is True + assert global_state["session_closed"] is True + + +def test_two_scopes() -> None: + global_context.set({}) + global_state = global_context.get() + with client.websocket_connect("/two-scopes") as websocket: + data = websocket.receive_json() + assert data["func_is_open"] is True + assert data["req_is_open"] is True + assert global_state["session_closed"] is True + + +def test_sub() -> None: + global_context.set({}) + global_state = global_context.get() + with client.websocket_connect("/sub") as websocket: + data = websocket.receive_json() + assert data["named_session_open"] is True + assert data["session_open"] is True + assert global_state["session_closed"] is True + assert global_state["named_session_closed"] is True + + +def test_broken_scope() -> None: + with pytest.raises( + FastAPIError, + match='The dependency "get_named_func_session" has a scope of "request", it cannot depend on dependencies with scope "function"', + ): + + @app.websocket("/broken-scope") + async def get_broken( + websocket: WebSocket, sessions: BrokenSessionsDep + ) -> Any: # pragma: no cover + pass + + +def test_named_function_scope() -> None: + global_context.set({}) + global_state = global_context.get() + with client.websocket_connect("/named-function-scope") as websocket: + data = websocket.receive_json() + assert data["named_session_open"] is True + assert data["session_open"] is True + assert global_state["session_closed"] is True + assert global_state["named_func_session_closed"] is True + + +def test_regular_function_scope() -> None: + global_context.set({}) + global_state = global_context.get() + with client.websocket_connect("/regular-function-scope") as websocket: + data = websocket.receive_json() + assert data["named_session_open"] is True + assert data["session_open"] is True + assert global_state["session_closed"] is True diff --git a/tests/test_get_model_definitions_formfeed_escape.py b/tests/test_get_model_definitions_formfeed_escape.py index 439e6d448..6601585ef 100644 --- a/tests/test_get_model_definitions_formfeed_escape.py +++ b/tests/test_get_model_definitions_formfeed_escape.py @@ -5,7 +5,6 @@ import fastapi.openapi.utils import pydantic.schema import pytest from fastapi import FastAPI -from fastapi._compat import v1 from pydantic import BaseModel from starlette.testclient import TestClient @@ -165,6 +164,8 @@ def test_model_description_escaped_with_formfeed(sort_reversed: bool): Test `get_model_definitions` with models passed in different order. """ + from fastapi._compat import v1 + all_fields = fastapi.openapi.utils.get_fields_from_routes(app.routes) flat_models = v1.get_flat_models_from_fields(all_fields, known_models=set()) diff --git a/tests/test_lifespan_scoped_dependencies/test_dependency_overrides.py b/tests/test_lifespan_scoped_dependencies/test_dependency_overrides.py index eb61ed248..3fd337c35 100644 --- a/tests/test_lifespan_scoped_dependencies/test_dependency_overrides.py +++ b/tests/test_lifespan_scoped_dependencies/test_dependency_overrides.py @@ -16,7 +16,7 @@ from fastapi import ( Request, WebSocket, ) -from fastapi.exceptions import DependencyScopeConflict +from fastapi.exceptions import DependencyScopeError from fastapi.params import Security from fastapi.security import SecurityScopes from fastapi.testclient import TestClient @@ -107,7 +107,7 @@ def test_endpoint_dependencies( None, Depends( dependency_factory.get_dependency(), - dependency_scope="lifespan", + scope="lifespan", use_cache=use_cache, ), ], @@ -147,7 +147,7 @@ def test_router_dependencies( depends = Depends( dependency_factory.get_dependency(), - dependency_scope="lifespan", + scope="lifespan", use_cache=use_cache, ) @@ -185,12 +185,12 @@ def test_router_dependencies( @pytest.mark.parametrize("use_cache", [True, False]) @pytest.mark.parametrize("dependency_style", list(DependencyStyle)) @pytest.mark.parametrize("routing_style", ["app", "router"]) -@pytest.mark.parametrize("main_dependency_scope", ["endpoint", "lifespan"]) +@pytest.mark.parametrize("main_dependency_scope", ["function", "request", "lifespan"]) def test_dependency_cache_in_same_dependency( dependency_style: DependencyStyle, routing_style, use_cache, - main_dependency_scope: Literal["endpoint", "lifespan"], + main_dependency_scope: Literal["function", "request", "lifespan"], is_websocket, ): dependency_factory = DependencyFactory(dependency_style) @@ -198,7 +198,7 @@ def test_dependency_cache_in_same_dependency( depends = Depends( dependency_factory.get_dependency(), - dependency_scope="lifespan", + scope="lifespan", use_cache=use_cache, ) @@ -225,7 +225,7 @@ def test_dependency_cache_in_same_dependency( Depends( dependency, use_cache=use_cache, - dependency_scope=main_dependency_scope, + scope=main_dependency_scope, ), ], ) @@ -275,7 +275,7 @@ def test_dependency_cache_in_same_endpoint( depends = Depends( dependency_factory.get_dependency(), - dependency_scope="lifespan", + scope="lifespan", use_cache=use_cache, ) @@ -344,7 +344,7 @@ def test_dependency_cache_in_different_endpoints( depends = Depends( dependency_factory.get_dependency(), - dependency_scope="lifespan", + scope="lifespan", use_cache=use_cache, ) @@ -425,7 +425,7 @@ def test_no_cached_dependency( depends = Depends( dependency_factory.get_dependency(), - dependency_scope="lifespan", + scope="lifespan", use_cache=False, ) @@ -495,11 +495,11 @@ def test_override_lifespan_scoped_dependency_cannot_use_endpoint_scoped_paramete path="/test", is_websocket=is_websocket, annotation=Annotated[ - None, Depends(dependency_func, dependency_scope="lifespan") + None, Depends(dependency_func, scope="lifespan") ], ) - with pytest.raises(DependencyScopeConflict): + with pytest.raises(DependencyScopeError): with TestClient(app): pass @@ -515,7 +515,7 @@ def test_non_override_lifespan_scoped_dependency_can_use_overridden_lifespan_sco async def lifespan_scoped_dependency( param: Annotated[ int, - Depends(dependency_factory.get_dependency(), dependency_scope="lifespan"), + Depends(dependency_factory.get_dependency(), scope="lifespan"), ], ) -> AsyncGenerator[int, None]: yield param @@ -527,7 +527,7 @@ def test_non_override_lifespan_scoped_dependency_can_use_overridden_lifespan_sco path="/test", is_websocket=is_websocket, annotation=Annotated[ - int, Depends(lifespan_scoped_dependency, dependency_scope="lifespan") + int, Depends(lifespan_scoped_dependency, scope="lifespan") ], ) @@ -568,13 +568,13 @@ def test_override_lifespan_scoped_dependency_cannot_use_endpoint_scoped_dependen path="/test", is_websocket=is_websocket, annotation=Annotated[ - None, Depends(dependency_func, dependency_scope="lifespan") + None, Depends(dependency_func, scope="lifespan") ], ) app.dependency_overrides[dependency_func] = override_dependency_func - with pytest.raises(DependencyScopeConflict): + with pytest.raises(DependencyScopeError): with TestClient(app): pass @@ -591,7 +591,7 @@ def test_bad_override_lifespan_scoped_dependencies( depends = Depends( dependency_factory.get_dependency(), - dependency_scope="lifespan", + scope="lifespan", use_cache=use_cache, ) diff --git a/tests/test_lifespan_scoped_dependencies/test_endpoint_usage.py b/tests/test_lifespan_scoped_dependencies/test_endpoint_usage.py index 0770c07fb..23875e978 100644 --- a/tests/test_lifespan_scoped_dependencies/test_endpoint_usage.py +++ b/tests/test_lifespan_scoped_dependencies/test_endpoint_usage.py @@ -21,7 +21,7 @@ from fastapi import ( ) from fastapi.dependencies.utils import get_endpoint_dependant from fastapi.exceptions import ( - DependencyScopeConflict, + DependencyScopeError, InvalidDependencyScope, UninitializedLifespanDependency, ) @@ -103,7 +103,7 @@ def test_endpoint_dependencies( None, Depends( dependency_factory.get_dependency(), - dependency_scope="lifespan", + scope="lifespan", use_cache=use_cache, ), ], @@ -138,7 +138,7 @@ def test_router_dependencies( depends = Depends( dependency_factory.get_dependency(), - dependency_scope="lifespan", + scope="lifespan", use_cache=use_cache, ) @@ -171,19 +171,19 @@ def test_router_dependencies( @pytest.mark.parametrize("use_cache", [True, False]) @pytest.mark.parametrize("dependency_style", list(DependencyStyle)) @pytest.mark.parametrize("routing_style", ["app", "router"]) -@pytest.mark.parametrize("main_dependency_scope", ["endpoint", "lifespan"]) +@pytest.mark.parametrize("main_dependency_scope", ["request", "function", "lifespan"]) def test_dependency_cache_in_same_dependency( dependency_style: DependencyStyle, routing_style, use_cache, - main_dependency_scope: Literal["endpoint", "lifespan"], + main_dependency_scope: Literal["request", "function", "lifespan"], is_websocket: bool, ): dependency_factory = DependencyFactory(dependency_style) depends = Depends( dependency_factory.get_dependency(), - dependency_scope="lifespan", + scope="lifespan", use_cache=use_cache, ) @@ -210,7 +210,7 @@ def test_dependency_cache_in_same_dependency( Depends( dependency, use_cache=use_cache, - dependency_scope=main_dependency_scope, + scope=main_dependency_scope, ), ], ) @@ -253,7 +253,7 @@ def test_dependency_cache_in_same_endpoint( depends = Depends( dependency_factory.get_dependency(), - dependency_scope="lifespan", + scope="lifespan", use_cache=use_cache, ) @@ -315,7 +315,7 @@ def test_dependency_cache_in_different_endpoints( depends = Depends( dependency_factory.get_dependency(), - dependency_scope="lifespan", + scope="lifespan", use_cache=use_cache, ) @@ -391,7 +391,7 @@ def test_no_cached_dependency( depends = Depends( dependency_factory.get_dependency(), - dependency_scope="lifespan", + scope="lifespan", use_cache=False, ) @@ -448,13 +448,13 @@ def test_lifespan_scoped_dependency_cannot_use_endpoint_scoped_parameters( app = FastAPI() - with pytest.raises(DependencyScopeConflict): + with pytest.raises(DependencyScopeError): create_endpoint_1_annotation( router=app, path="/test", is_websocket=is_websocket, annotation=Annotated[ - None, Depends(dependency_func, dependency_scope="lifespan") + None, Depends(dependency_func, scope="lifespan") ], ) @@ -469,7 +469,7 @@ def test_lifespan_scoped_dependency_can_use_other_lifespan_scoped_dependencies( async def lifespan_scoped_dependency( param: Annotated[ int, - Depends(dependency_factory.get_dependency(), dependency_scope="lifespan"), + Depends(dependency_factory.get_dependency(), scope="lifespan"), ], ) -> AsyncGenerator[int, None]: yield param @@ -503,8 +503,12 @@ def test_lifespan_scoped_dependency_can_use_other_lifespan_scoped_dependencies( (DependencyStyle.ASYNC_GENERATOR, True), ], ) +@pytest.mark.parametrize("endpoint_dependency_scope", ["request", "function"]) def test_the_same_dependency_can_work_in_different_scopes( - dependency_style: DependencyStyle, supports_teardown, is_websocket + dependency_style: DependencyStyle, + supports_teardown, + is_websocket, + endpoint_dependency_scope: Literal["request", "function"], ): dependency_factory = DependencyFactory(dependency_style) app = FastAPI() @@ -515,11 +519,11 @@ def test_the_same_dependency_can_work_in_different_scopes( is_websocket=is_websocket, annotation1=Annotated[ int, - Depends(dependency_factory.get_dependency(), dependency_scope="endpoint"), + Depends(dependency_factory.get_dependency(), scope=endpoint_dependency_scope), ], annotation2=Annotated[ int, - Depends(dependency_factory.get_dependency(), dependency_scope="lifespan"), + Depends(dependency_factory.get_dependency(), scope="lifespan"), ], ) if is_websocket: @@ -620,7 +624,7 @@ def test_lifespan_scoped_dependency_can_be_used_alongside_custom_lifespans( is_websocket=is_websocket, annotation=Annotated[ int, - Depends(dependency_factory.get_dependency(), dependency_scope="lifespan"), + Depends(dependency_factory.get_dependency(), scope="lifespan"), ], expected_value=1, ) @@ -650,13 +654,13 @@ def test_lifespan_scoped_dependency_cannot_use_endpoint_scoped_dependencies( app = FastAPI() - with pytest.raises(DependencyScopeConflict): + with pytest.raises(DependencyScopeError): create_endpoint_1_annotation( router=app, path="/test", is_websocket=is_websocket, annotation=Annotated[ - None, Depends(dependency_func, dependency_scope="lifespan") + None, Depends(dependency_func, scope="lifespan") ], ) @@ -679,7 +683,7 @@ def test_dependencies_must_provide_correct_dependency_scope( with pytest.raises( InvalidDependencyScope, - match=r'Dependency "value" of .* has an invalid scope: ' r'"incorrect"', + match=r'Dependency received an invalid scope: "incorrect"', ): create_endpoint_1_annotation( router=router, @@ -689,7 +693,7 @@ def test_dependencies_must_provide_correct_dependency_scope( None, Depends( dependency_factory.get_dependency(), - dependency_scope="incorrect", + scope="incorrect", use_cache=use_cache, ), ], @@ -714,12 +718,12 @@ def test_endpoints_report_incorrect_dependency_scope( depends = Depends( dependency_factory.get_dependency(), - dependency_scope="lifespan", + scope="lifespan", use_cache=use_cache, ) # We intentionally change the dependency scope here to bypass the # validation at the function level. - depends.dependency_scope = "asdad" + depends.scope = "asdad" with pytest.raises(InvalidDependencyScope): create_endpoint_1_annotation( @@ -739,11 +743,11 @@ def test_endpoints_report_incorrect_dependency_scope_at_router_scope( ): dependency_factory = DependencyFactory(DependencyStyle.ASYNC_GENERATOR) - depends = Depends(dependency_factory.get_dependency(), dependency_scope="lifespan") + depends = Depends(dependency_factory.get_dependency(), scope="lifespan") # We intentionally change the dependency scope here to bypass the # validation at the function level. - depends.dependency_scope = "asdad" + depends.scope = "asdad" if routing_style == "app": app = FastAPI(dependencies=[depends]) @@ -777,7 +781,7 @@ def test_endpoints_report_uninitialized_dependency( depends = Depends( dependency_factory.get_dependency(), - dependency_scope="lifespan", + scope="lifespan", use_cache=use_cache, ) @@ -827,7 +831,7 @@ def test_endpoints_report_uninitialized_internal_lifespan( depends = Depends( dependency_factory.get_dependency(), - dependency_scope="lifespan", + scope="lifespan", use_cache=use_cache, ) @@ -867,7 +871,7 @@ def test_bad_lifespan_scoped_dependencies( dependency_factory = DependencyFactory(dependency_style, should_error=True) depends = Depends( dependency_factory.get_dependency(), - dependency_scope="lifespan", + scope="lifespan", use_cache=use_cache, ) @@ -904,7 +908,7 @@ def test_endpoint_dependant_backwards_compatibility(): dependency1: Annotated[int, Depends(dependency_factory.get_dependency())], dependency2: Annotated[ int, - Depends(dependency_factory.get_dependency(), dependency_scope="lifespan"), + Depends(dependency_factory.get_dependency(), scope="lifespan"), ], ): pass # pragma: nocover diff --git a/tests/test_no_schema_split.py b/tests/test_no_schema_split.py new file mode 100644 index 000000000..b0b5958c1 --- /dev/null +++ b/tests/test_no_schema_split.py @@ -0,0 +1,203 @@ +# Test with parts from, and to verify the report in: +# https://github.com/fastapi/fastapi/discussions/14177 +# Made an issue in: +# https://github.com/fastapi/fastapi/issues/14247 +from enum import Enum +from typing import List + +from fastapi import FastAPI +from fastapi.testclient import TestClient +from inline_snapshot import snapshot +from pydantic import BaseModel, Field + +from tests.utils import pydantic_snapshot + + +class MessageEventType(str, Enum): + alpha = "alpha" + beta = "beta" + + +class MessageEvent(BaseModel): + event_type: MessageEventType = Field(default=MessageEventType.alpha) + output: str + + +class MessageOutput(BaseModel): + body: str = "" + events: List[MessageEvent] = [] + + +class Message(BaseModel): + input: str + output: MessageOutput + + +app = FastAPI(title="Minimal FastAPI App", version="1.0.0") + + +@app.post("/messages", response_model=Message) +async def create_message(input_message: str) -> Message: + return Message( + input=input_message, + output=MessageOutput(body=f"Processed: {input_message}"), + ) + + +client = TestClient(app) + + +def test_create_message(): + response = client.post("/messages", params={"input_message": "Hello"}) + assert response.status_code == 200, response.text + assert response.json() == { + "input": "Hello", + "output": {"body": "Processed: Hello", "events": []}, + } + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "Minimal FastAPI App", "version": "1.0.0"}, + "paths": { + "/messages": { + "post": { + "summary": "Create Message", + "operationId": "create_message_messages_post", + "parameters": [ + { + "name": "input_message", + "in": "query", + "required": True, + "schema": {"type": "string", "title": "Input Message"}, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Message" + } + } + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + } + } + }, + "components": { + "schemas": { + "HTTPValidationError": { + "properties": { + "detail": { + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + "type": "array", + "title": "Detail", + } + }, + "type": "object", + "title": "HTTPValidationError", + }, + "Message": { + "properties": { + "input": {"type": "string", "title": "Input"}, + "output": {"$ref": "#/components/schemas/MessageOutput"}, + }, + "type": "object", + "required": ["input", "output"], + "title": "Message", + }, + "MessageEvent": { + "properties": { + "event_type": pydantic_snapshot( + v2=snapshot( + { + "$ref": "#/components/schemas/MessageEventType", + "default": "alpha", + } + ), + v1=snapshot( + { + "allOf": [ + { + "$ref": "#/components/schemas/MessageEventType" + } + ], + "default": "alpha", + } + ), + ), + "output": {"type": "string", "title": "Output"}, + }, + "type": "object", + "required": ["output"], + "title": "MessageEvent", + }, + "MessageEventType": pydantic_snapshot( + v2=snapshot( + { + "type": "string", + "enum": ["alpha", "beta"], + "title": "MessageEventType", + } + ), + v1=snapshot( + { + "type": "string", + "enum": ["alpha", "beta"], + "title": "MessageEventType", + "description": "An enumeration.", + } + ), + ), + "MessageOutput": { + "properties": { + "body": {"type": "string", "title": "Body", "default": ""}, + "events": { + "items": {"$ref": "#/components/schemas/MessageEvent"}, + "type": "array", + "title": "Events", + "default": [], + }, + }, + "type": "object", + "title": "MessageOutput", + }, + "ValidationError": { + "properties": { + "loc": { + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + "type": "array", + "title": "Location", + }, + "msg": {"type": "string", "title": "Message"}, + "type": {"type": "string", "title": "Error Type"}, + }, + "type": "object", + "required": ["loc", "msg", "type"], + "title": "ValidationError", + }, + } + }, + } + ) diff --git a/tests/test_params_repr.py b/tests/test_params_repr.py index 8921026b2..1529fe72f 100644 --- a/tests/test_params_repr.py +++ b/tests/test_params_repr.py @@ -2,7 +2,7 @@ from typing import Any, List import pytest from dirty_equals import IsOneOf -from fastapi.params import Body, Cookie, Depends, Header, Param, Path, Query +from fastapi.params import Body, Cookie, Header, Param, Path, Query test_data: List[Any] = ["teststr", None, ..., 1, []] @@ -142,32 +142,3 @@ def test_body_repr_number(): def test_body_repr_list(): assert repr(Body([])) == "Body([])" - - -@pytest.mark.parametrize( - ["depends", "expected_repr"], - [ - [Depends(), "Depends(NoneType)"], - [Depends(get_user), "Depends(get_user)"], - [Depends(use_cache=False), "Depends(NoneType, use_cache=False)"], - [Depends(get_user, use_cache=False), "Depends(get_user, use_cache=False)"], - [ - Depends(dependency_scope="lifespan"), - 'Depends(NoneType, dependency_scope="lifespan")', - ], - [ - Depends(get_user, dependency_scope="lifespan"), - 'Depends(get_user, dependency_scope="lifespan")', - ], - [ - Depends(use_cache=False, dependency_scope="lifespan"), - 'Depends(NoneType, use_cache=False, dependency_scope="lifespan")', - ], - [ - Depends(get_user, use_cache=False, dependency_scope="lifespan"), - 'Depends(get_user, use_cache=False, dependency_scope="lifespan")', - ], - ], -) -def test_depends_repr(depends, expected_repr): - assert repr(depends) == expected_repr diff --git a/tests/test_pydantic_v1_v2_multifile/test_multifile.py b/tests/test_pydantic_v1_v2_multifile/test_multifile.py index 4472bd73e..e66d102fb 100644 --- a/tests/test_pydantic_v1_v2_multifile/test_multifile.py +++ b/tests/test_pydantic_v1_v2_multifile/test_multifile.py @@ -1028,17 +1028,6 @@ def test_openapi_schema(): "type": "object", "title": "HTTPValidationError", }, - "SubItem-Output": { - "properties": { - "new_sub_name": { - "type": "string", - "title": "New Sub Name", - } - }, - "type": "object", - "required": ["new_sub_name"], - "title": "SubItem", - }, "ValidationError": { "properties": { "loc": { @@ -1113,11 +1102,11 @@ def test_openapi_schema(): "title": "New Description", }, "new_sub": { - "$ref": "#/components/schemas/SubItem-Output" + "$ref": "#/components/schemas/tests__test_pydantic_v1_v2_multifile__modelsv2__SubItem" }, "new_multi": { "items": { - "$ref": "#/components/schemas/SubItem-Output" + "$ref": "#/components/schemas/tests__test_pydantic_v1_v2_multifile__modelsv2__SubItem" }, "type": "array", "title": "New Multi", diff --git a/tests/test_response_model_as_return_annotation.py b/tests/test_response_model_as_return_annotation.py index c3c0ed6c4..1745c69b6 100644 --- a/tests/test_response_model_as_return_annotation.py +++ b/tests/test_response_model_as_return_annotation.py @@ -2,12 +2,13 @@ from typing import List, Union import pytest from fastapi import FastAPI -from fastapi._compat import v1 from fastapi.exceptions import FastAPIError, ResponseValidationError from fastapi.responses import JSONResponse, Response from fastapi.testclient import TestClient from pydantic import BaseModel +from tests.utils import needs_pydanticv1 + class BaseUser(BaseModel): name: str @@ -511,7 +512,10 @@ def test_invalid_response_model_field(): # TODO: remove when dropping Pydantic v1 support +@needs_pydanticv1 def test_invalid_response_model_field_pv1(): + from fastapi._compat import v1 + app = FastAPI() class Model(v1.BaseModel): diff --git a/tests/test_top_level_security_scheme_in_openapi.py b/tests/test_top_level_security_scheme_in_openapi.py new file mode 100644 index 000000000..e2de31af5 --- /dev/null +++ b/tests/test_top_level_security_scheme_in_openapi.py @@ -0,0 +1,60 @@ +# Test security scheme at the top level, including OpenAPI +# Ref: https://github.com/fastapi/fastapi/discussions/14263 +# Ref: https://github.com/fastapi/fastapi/issues/14271 +from fastapi import Depends, FastAPI +from fastapi.security import HTTPBearer +from fastapi.testclient import TestClient +from inline_snapshot import snapshot + +app = FastAPI() + +bearer_scheme = HTTPBearer() + + +@app.get("/", dependencies=[Depends(bearer_scheme)]) +async def get_root(): + return {"message": "Hello, World!"} + + +client = TestClient(app) + + +def test_get_root(): + response = client.get("/", headers={"Authorization": "Bearer token"}) + assert response.status_code == 200, response.text + assert response.json() == {"message": "Hello, World!"} + + +def test_get_root_no_token(): + response = client.get("/") + assert response.status_code == 403, response.text + assert response.json() == {"detail": "Not authenticated"} + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/": { + "get": { + "summary": "Get Root", + "operationId": "get_root__get", + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + "security": [{"HTTPBearer": []}], + } + } + }, + "components": { + "securitySchemes": {"HTTPBearer": {"type": "http", "scheme": "bearer"}} + }, + } + ) diff --git a/tests/test_tutorial/test_dependencies/test_tutorial008e.py b/tests/test_tutorial/test_dependencies/test_tutorial008e.py new file mode 100644 index 000000000..1ae9ab2cd --- /dev/null +++ b/tests/test_tutorial/test_dependencies/test_tutorial008e.py @@ -0,0 +1,27 @@ +import importlib + +import pytest +from fastapi.testclient import TestClient + +from ...utils import needs_py39 + + +@pytest.fixture( + name="client", + params=[ + "tutorial008e", + "tutorial008e_an", + pytest.param("tutorial008e_an_py39", marks=needs_py39), + ], +) +def get_client(request: pytest.FixtureRequest): + mod = importlib.import_module(f"docs_src.dependencies.{request.param}") + + client = TestClient(mod.app) + return client + + +def test_get_users_me(client: TestClient): + response = client.get("/users/me") + assert response.status_code == 200, response.text + assert response.json() == "Rick"