diff --git a/docs/de/docs/advanced/advanced-dependencies.md b/docs/de/docs/advanced/advanced-dependencies.md
index da5f28c7c..2254dcf53 100644
--- a/docs/de/docs/advanced/advanced-dependencies.md
+++ b/docs/de/docs/advanced/advanced-dependencies.md
@@ -70,12 +70,22 @@ Wenn Sie das hier alles verstanden haben, wissen Sie bereits, wie diese Sicherhe
Sie benötigen diese technischen Details höchstwahrscheinlich nicht.
-Diese Details sind hauptsächlich nützlich, wenn Sie eine FastAPI-Anwendung haben, die älter als 0.118.0 ist, und Sie auf Probleme mit Abhängigkeiten mit `yield` stoßen.
+Diese Details sind hauptsächlich nützlich, wenn Sie eine FastAPI-Anwendung haben, die älter als 0.121.0 ist, und Sie auf Probleme mit Abhängigkeiten mit `yield` stoßen.
///
Abhängigkeiten mit `yield` haben sich im Laufe der Zeit weiterentwickelt, um verschiedene Anwendungsfälle abzudecken und einige Probleme zu beheben, hier ist eine Zusammenfassung der Änderungen.
+### Abhängigkeiten mit `yield` und `scope` { #dependencies-with-yield-and-scope }
+
+In Version 0.121.0 hat FastAPI Unterstützung für `Depends(scope="function")` für Abhängigkeiten mit `yield` hinzugefügt.
+
+Mit `Depends(scope="function")` wird der Exit-Code nach `yield` direkt nach dem Ende der *Pfadoperation-Funktion* ausgeführt, bevor die Response an den Client gesendet wird.
+
+Und bei Verwendung von `Depends(scope="request")` (dem Default) wird der Exit-Code nach `yield` ausgeführt, nachdem die Response gesendet wurde.
+
+Mehr dazu finden Sie in der Dokumentation zu [Abhängigkeiten mit `yield` – Frühes Beenden und `scope`](../tutorial/dependencies/dependencies-with-yield.md#early-exit-and-scope).
+
### Abhängigkeiten mit `yield` und `StreamingResponse`, Technische Details { #dependencies-with-yield-and-streamingresponse-technical-details }
Vor FastAPI 0.118.0 wurde bei Verwendung einer Abhängigkeit mit `yield` der Exit-Code nach der *Pfadoperation-Funktion* ausgeführt, aber unmittelbar bevor die Response gesendet wurde.
diff --git a/docs/de/docs/tutorial/dependencies/dependencies-with-yield.md b/docs/de/docs/tutorial/dependencies/dependencies-with-yield.md
index e65b073a2..34db6c6be 100644
--- a/docs/de/docs/tutorial/dependencies/dependencies-with-yield.md
+++ b/docs/de/docs/tutorial/dependencies/dependencies-with-yield.md
@@ -184,6 +184,51 @@ Wenn Sie in dem Code der *Pfadoperation-Funktion* irgendeine Exception auslösen
///
+## Frühes Beenden und `scope` { #early-exit-and-scope }
+
+Normalerweise wird der Exit-Code von Abhängigkeiten mit `yield` ausgeführt **nachdem die Response** an den Client gesendet wurde.
+
+Wenn Sie aber wissen, dass Sie die Abhängigkeit nach der Rückkehr aus der *Pfadoperation-Funktion* nicht mehr benötigen, können Sie `Depends(scope="function")` verwenden, um FastAPI mitzuteilen, dass es die Abhängigkeit nach der Rückkehr aus der *Pfadoperation-Funktion* schließen soll, jedoch **bevor** die **Response gesendet wird**.
+
+{* ../../docs_src/dependencies/tutorial008e_an_py39.py hl[12,16] *}
+
+`Depends()` erhält einen `scope`-Parameter, der sein kann:
+
+* `"function"`: startet die Abhängigkeit vor der *Pfadoperation-Funktion*, die den Request bearbeitet, beendet die Abhängigkeit nach dem Ende der *Pfadoperation-Funktion*, aber **bevor** die Response an den Client zurückgesendet wird. Die Abhängigkeitsfunktion wird also **um** die *Pfadoperation-**Funktion*** **herum** ausgeführt.
+* `"request"`: startet die Abhängigkeit vor der *Pfadoperation-Funktion*, die den Request bearbeitet (ähnlich wie bei `"function"`), beendet sie jedoch **nachdem** die Response an den Client zurückgesendet wurde. Die Abhängigkeitsfunktion wird also **um** den **Request**- und Response-Zyklus **herum** ausgeführt.
+
+Wenn nicht angegeben und die Abhängigkeit `yield` hat, hat sie standardmäßig einen `scope` von `"request"`.
+
+### `scope` für Unterabhängigkeiten { #scope-for-sub-dependencies }
+
+Wenn Sie eine Abhängigkeit mit `scope="request"` (dem Default) deklarieren, muss jede Unterabhängigkeit ebenfalls einen `scope` von `"request"` haben.
+
+Eine Abhängigkeit mit `scope` von `"function"` kann jedoch Abhängigkeiten mit `scope` von `"function"` und `scope` von `"request"` haben.
+
+Das liegt daran, dass jede Abhängigkeit in der Lage sein muss, ihren Exit-Code vor den Unterabhängigkeiten auszuführen, da sie diese während ihres Exit-Codes möglicherweise noch verwenden muss.
+
+```mermaid
+sequenceDiagram
+
+participant client as Client
+participant dep_req as Abhängigkeit scope="request"
+participant dep_func as Abhängigkeit scope="function"
+participant operation as Pfadoperation
+
+ client ->> dep_req: Startet den Request
+ Note over dep_req: Führt den Code bis zum yield aus
+ dep_req ->> dep_func: Reicht Abhängigkeit weiter
+ Note over dep_func: Führt den Code bis zum yield aus
+ dep_func ->> operation: Führt Pfadoperation mit Abhängigkeit aus
+ operation ->> dep_func: Kehrt aus Pfadoperation zurück
+ Note over dep_func: Führt Code nach yield aus
+ Note over dep_func: ✅ Abhängigkeit geschlossen
+ dep_func ->> client: Sendet Response an Client
+ Note over client: Response gesendet
+ Note over dep_req: Führt Code nach yield aus
+ Note over dep_req: ✅ Abhängigkeit geschlossen
+```
+
## Abhängigkeiten mit `yield`, `HTTPException`, `except` und Hintergrundtasks { #dependencies-with-yield-httpexception-except-and-background-tasks }
Abhängigkeiten mit `yield` haben sich im Laufe der Zeit weiterentwickelt, um verschiedene Anwendungsfälle abzudecken und einige Probleme zu beheben.
diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md
index 9380fb7d4..688e65e71 100644
--- a/docs/en/docs/release-notes.md
+++ b/docs/en/docs/release-notes.md
@@ -7,6 +7,17 @@ hide:
## Latest Changes
+### Translations
+
+* 🌐 Sync Russian docs. PR [#14331](https://github.com/fastapi/fastapi/pull/14331) by [@YuriiMotov](https://github.com/YuriiMotov).
+* 🌐 Sync German docs. PR [#14317](https://github.com/fastapi/fastapi/pull/14317) by [@nilslindemann](https://github.com/nilslindemann).
+
+## 0.121.1
+
+### Fixes
+
+* 🐛 Fix `Depends(func, scope='function')` for top level (parameterless) dependencies. PR [#14301](https://github.com/fastapi/fastapi/pull/14301) by [@luzzodev](https://github.com/luzzodev).
+
### 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).
diff --git a/docs/ru/docs/advanced/advanced-dependencies.md b/docs/ru/docs/advanced/advanced-dependencies.md
index 75a6f0d1f..339c0a363 100644
--- a/docs/ru/docs/advanced/advanced-dependencies.md
+++ b/docs/ru/docs/advanced/advanced-dependencies.md
@@ -70,12 +70,22 @@ checker(q="somequery")
Скорее всего, вам не понадобятся эти технические детали.
-Они полезны главным образом, если у вас было приложение FastAPI версии ниже 0.118.0 и вы столкнулись с проблемами зависимостей с `yield`.
+Они полезны главным образом, если у вас было приложение FastAPI версии ниже 0.121.0 и вы столкнулись с проблемами зависимостей с `yield`.
///
Зависимости с `yield` со временем изменялись, чтобы учитывать разные случаи применения и исправлять проблемы. Ниже — краткое резюме изменений.
+### Зависимости с `yield` и `scope` { #dependencies-with-yield-and-scope }
+
+В версии 0.121.0 FastAPI добавил поддержку `Depends(scope="function")` для зависимостей с `yield`.
+
+При использовании `Depends(scope="function")` код после `yield` выполняется сразу после завершения *функции-обработчика пути*, до отправки ответа клиенту.
+
+А при использовании `Depends(scope="request")` (значение по умолчанию) код после `yield` выполняется после отправки ответа.
+
+Подробнее читайте в документации: [Зависимости с `yield` — раннее завершение и `scope`](../tutorial/dependencies/dependencies-with-yield.md#early-exit-and-scope).
+
### Зависимости с `yield` и `StreamingResponse`, технические детали { #dependencies-with-yield-and-streamingresponse-technical-details }
До FastAPI 0.118.0, если вы использовали зависимость с `yield`, код после `yield` выполнялся после возврата из *функции-обработчика пути*, но прямо перед отправкой ответа.
diff --git a/docs/ru/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md b/docs/ru/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md
new file mode 100644
index 000000000..95481bc66
--- /dev/null
+++ b/docs/ru/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md
@@ -0,0 +1,133 @@
+# Миграция с Pydantic v1 на Pydantic v2 { #migrate-from-pydantic-v1-to-pydantic-v2 }
+
+Если у вас старое приложение FastAPI, возможно, вы используете Pydantic версии 1.
+
+FastAPI поддерживает и Pydantic v1, и v2 начиная с версии 0.100.0.
+
+Если у вас был установлен Pydantic v2, использовался он. Если вместо этого был установлен Pydantic v1 — использовался он.
+
+Сейчас Pydantic v1 объявлен устаревшим, и поддержка его будет удалена в следующих версиях FastAPI, поэтому вам следует **перейти на Pydantic v2**. Так вы получите последние возможности, улучшения и исправления.
+
+/// warning | Предупреждение
+
+Кроме того, команда Pydantic прекратила поддержку Pydantic v1 для последних версий Python, начиная с **Python 3.14**.
+
+Если вы хотите использовать последние возможности Python, вам нужно убедиться, что вы используете Pydantic v2.
+
+///
+
+Если у вас старое приложение FastAPI с Pydantic v1, здесь я покажу, как мигрировать на Pydantic v2, и **новые возможности в FastAPI 0.119.0**, которые помогут выполнить постепенную миграцию.
+
+## Официальное руководство { #official-guide }
+
+У Pydantic есть официальное руководство по миграции с v1 на v2.
+
+Там также описано, что изменилось, как валидации стали более корректными и строгими, возможные нюансы и т.д.
+
+Прочитайте его, чтобы лучше понять, что изменилось.
+
+## Тесты { #tests }
+
+Убедитесь, что у вас есть [тесты](../tutorial/testing.md){.internal-link target=_blank} для вашего приложения и что вы запускаете их в системе непрерывной интеграции (CI).
+
+Так вы сможете выполнить обновление и убедиться, что всё работает как ожидается.
+
+## `bump-pydantic` { #bump-pydantic }
+
+Во многих случаях, когда вы используете обычные Pydantic‑модели без пользовательских настроек, вы сможете автоматизировать большую часть процесса миграции с Pydantic v1 на Pydantic v2.
+
+Вы можете использовать `bump-pydantic` от той же команды Pydantic.
+
+Этот инструмент поможет автоматически внести большую часть необходимых изменений в код.
+
+После этого запустите тесты и проверьте, что всё работает. Если да — на этом всё. 😎
+
+## Pydantic v1 в v2 { #pydantic-v1-in-v2 }
+
+Pydantic v2 включает всё из Pydantic v1 как подмодуль `pydantic.v1`.
+
+Это означает, что вы можете установить последнюю версию Pydantic v2 и импортировать и использовать старые компоненты Pydantic v1 из этого подмодуля так, как если бы у вас был установлен старый Pydantic v1.
+
+{* ../../docs_src/pydantic_v1_in_v2/tutorial001_an_py310.py hl[1,4] *}
+
+### Поддержка FastAPI для Pydantic v1 внутри v2 { #fastapi-support-for-pydantic-v1-in-v2 }
+
+Начиная с FastAPI 0.119.0, есть также частичная поддержка Pydantic v1 в составе Pydantic v2, чтобы упростить миграцию на v2.
+
+Таким образом, вы можете обновить Pydantic до последней версии 2 и сменить импорты на подмодуль `pydantic.v1` — во многих случаях всё просто заработает.
+
+{* ../../docs_src/pydantic_v1_in_v2/tutorial002_an_py310.py hl[2,5,15] *}
+
+/// warning | Предупреждение
+
+Имейте в виду, что так как команда Pydantic больше не поддерживает Pydantic v1 в последних версиях Python, начиная с Python 3.14, использование `pydantic.v1` также не поддерживается в Python 3.14 и выше.
+
+///
+
+### Pydantic v1 и v2 в одном приложении { #pydantic-v1-and-v2-on-the-same-app }
+
+В Pydantic **не поддерживается** ситуация, когда в одной модели Pydantic v2 используются поля, определённые как модели Pydantic v1, и наоборот.
+
+```mermaid
+graph TB
+ subgraph "❌ Not Supported"
+ direction TB
+ subgraph V2["Pydantic v2 Model"]
+ V1Field["Pydantic v1 Model"]
+ end
+ subgraph V1["Pydantic v1 Model"]
+ V2Field["Pydantic v2 Model"]
+ end
+ end
+
+ style V2 fill:#f9fff3
+ style V1 fill:#fff6f0
+ style V1Field fill:#fff6f0
+ style V2Field fill:#f9fff3
+```
+
+…но в одном и том же приложении вы можете иметь отдельные модели на Pydantic v1 и v2.
+
+```mermaid
+graph TB
+ subgraph "✅ Supported"
+ direction TB
+ subgraph V2["Pydantic v2 Model"]
+ V2Field["Pydantic v2 Model"]
+ end
+ subgraph V1["Pydantic v1 Model"]
+ V1Field["Pydantic v1 Model"]
+ end
+ end
+
+ style V2 fill:#f9fff3
+ style V1 fill:#fff6f0
+ style V1Field fill:#fff6f0
+ style V2Field fill:#f9fff3
+```
+
+В некоторых случаях можно использовать и модели Pydantic v1, и v2 в одной и той же операции пути (обработчике пути) вашего приложения FastAPI:
+
+{* ../../docs_src/pydantic_v1_in_v2/tutorial003_an_py310.py hl[2:3,6,12,21:22] *}
+
+В примере выше модель входных данных — это модель Pydantic v1, а модель выходных данных (указанная в `response_model=ItemV2`) — это модель Pydantic v2.
+
+### Параметры Pydantic v1 { #pydantic-v1-parameters }
+
+Если вам нужно использовать некоторые специфичные для FastAPI инструменты для параметров, такие как `Body`, `Query`, `Form` и т.п., с моделями Pydantic v1, вы можете импортировать их из `fastapi.temp_pydantic_v1_params`, пока завершаете миграцию на Pydantic v2:
+
+{* ../../docs_src/pydantic_v1_in_v2/tutorial004_an_py310.py hl[4,18] *}
+
+### Мигрируйте по шагам { #migrate-in-steps }
+
+/// tip | Совет
+
+Сначала попробуйте `bump-pydantic`. Если тесты проходят и всё работает, вы справились одной командой. ✨
+
+///
+
+Если `bump-pydantic` не подходит для вашего случая, вы можете использовать поддержку одновременной работы моделей Pydantic v1 и v2 в одном приложении, чтобы мигрировать на Pydantic v2 постепенно.
+
+Сначала обновите Pydantic до последней 2-й версии и измените импорты так, чтобы все ваши модели использовали `pydantic.v1`.
+
+Затем начните мигрировать ваши модели с Pydantic v1 на v2 группами, поэтапно. 🚶
diff --git a/docs/ru/docs/tutorial/dependencies/dependencies-with-yield.md b/docs/ru/docs/tutorial/dependencies/dependencies-with-yield.md
index 267faa406..7ff85246d 100644
--- a/docs/ru/docs/tutorial/dependencies/dependencies-with-yield.md
+++ b/docs/ru/docs/tutorial/dependencies/dependencies-with-yield.md
@@ -184,6 +184,51 @@ participant tasks as Background tasks
///
+## Ранний выход и `scope` { #early-exit-and-scope }
+
+Обычно «код выхода» зависимостей с `yield` выполняется **после того, как ответ** отправлен клиенту.
+
+Но если вы знаете, что не будете использовать зависимость после возврата из *функции-обработчика пути*, вы можете использовать `Depends(scope="function")`, чтобы сообщить FastAPI, что он должен закрыть зависимость после возврата из *функции-обработчика пути*, но **до того**, как **ответ будет отправлен**.
+
+{* ../../docs_src/dependencies/tutorial008e_an_py39.py hl[12,16] *}
+
+`Depends()` принимает параметр `scope`, который может быть:
+
+* `"function"`: начать зависимость до *функции-обработчика пути*, которая обрабатывает запрос, завершить зависимость после окончания *функции-обработчика пути*, но **до того**, как ответ будет отправлен обратно клиенту. То есть функция зависимости будет выполнена **вокруг** *функции-обработчика пути*.
+* `"request"`: начать зависимость до *функции-обработчика пути*, которая обрабатывает запрос (как и при использовании `"function"`), но завершить **после** того, как ответ будет отправлен обратно клиенту. То есть функция зависимости будет выполнена **вокруг** цикла запроса (**request**) и ответа.
+
+Если не указано и в зависимости есть `yield`, по умолчанию будет `scope` со значением `"request"`.
+
+### `scope` для подзависимостей { #scope-for-sub-dependencies }
+
+Когда вы объявляете зависимость с `scope="request"` (значение по умолчанию), любая подзависимость также должна иметь `scope` равный `"request"`.
+
+Но зависимость со `scope` равным `"function"` может иметь зависимости со `scope` `"function"` и со `scope` `"request"`.
+
+Это потому, что любая зависимость должна иметь возможность выполнить свой код выхода раньше подзависимостей, так как ей может понадобиться использовать их во время своего кода выхода.
+
+```mermaid
+sequenceDiagram
+
+participant client as Client
+participant dep_req as Зависимость scope="request"
+participant dep_func as Зависимость scope="function"
+participant operation as Функция-обработчик пути
+
+ client ->> dep_req: Запрос
+ Note over dep_req: Выполнить код до yield
+ dep_req ->> dep_func: Передать значение
+ Note over dep_func: Выполнить код до yield
+ dep_func ->> operation: Выполнить функцию-обработчик пути
+ operation ->> dep_func: Выход из функции-обработчика пути
+ Note over dep_func: Выполнить код после yield
+ Note over dep_func: ✅ Зависимость закрыта
+ dep_func ->> client: Отправить ответ клиенту
+ Note over client: Ответ отправлен
+ Note over dep_req: Выполнить код после yield
+ Note over dep_req: ✅ Зависимость закрыта
+```
+
## Зависимости с `yield`, `HTTPException`, `except` и фоновыми задачами { #dependencies-with-yield-httpexception-except-and-background-tasks }
Зависимости с `yield` со временем эволюционировали, чтобы покрыть разные сценарии и исправить некоторые проблемы.
diff --git a/fastapi/__init__.py b/fastapi/__init__.py
index f4a952bf5..5c4804e19 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.121.0"
+__version__ = "0.121.1"
from starlette import status as status
diff --git a/fastapi/dependencies/utils.py b/fastapi/dependencies/utils.py
index c5c6b69bb..4b69e39a1 100644
--- a/fastapi/dependencies/utils.py
+++ b/fastapi/dependencies/utils.py
@@ -129,7 +129,10 @@ def get_parameterless_sub_dependant(*, depends: params.Depends, path: str) -> De
if isinstance(depends, params.Security) and depends.scopes:
use_security_scopes.extend(depends.scopes)
return get_dependant(
- path=path, call=depends.dependency, security_scopes=use_security_scopes
+ path=path,
+ call=depends.dependency,
+ scope=depends.scope,
+ security_scopes=use_security_scopes,
)
diff --git a/tests/test_dependency_yield_scope.py b/tests/test_dependency_yield_scope.py
index a5227dd7a..d87164fe8 100644
--- a/tests/test_dependency_yield_scope.py
+++ b/tests/test_dependency_yield_scope.py
@@ -2,7 +2,7 @@ import json
from typing import Any, Tuple
import pytest
-from fastapi import Depends, FastAPI
+from fastapi import APIRouter, Depends, FastAPI, HTTPException
from fastapi.exceptions import FastAPIError
from fastapi.responses import StreamingResponse
from fastapi.testclient import TestClient
@@ -20,6 +20,11 @@ def dep_session() -> Any:
s.open = False
+def raise_after_yield() -> Any:
+ yield
+ raise HTTPException(status_code=503, detail="Exception after yield")
+
+
SessionFuncDep = Annotated[Session, Depends(dep_session, scope="function")]
SessionRequestDep = Annotated[Session, Depends(dep_session, scope="request")]
SessionDefaultDep = Annotated[Session, Depends(dep_session)]
@@ -64,6 +69,12 @@ RegularSessionsDep = Annotated[
]
app = FastAPI()
+router = APIRouter()
+
+
+@router.get("/")
+def get_index():
+ return {"status": "ok"}
@app.get("/function-scope")
@@ -124,6 +135,18 @@ def get_regular_function_scope(sessions: RegularSessionsDep) -> Any:
return StreamingResponse(iter_data())
+app.include_router(
+ prefix="/router-scope-function",
+ router=router,
+ dependencies=[Depends(raise_after_yield, scope="function")],
+)
+
+app.include_router(
+ prefix="/router-scope-request",
+ router=router,
+ dependencies=[Depends(raise_after_yield, scope="request")],
+)
+
client = TestClient(app)
@@ -182,3 +205,42 @@ def test_regular_function_scope() -> None:
data = response.json()
assert data["named_session_open"] is True
assert data["session_open"] is False
+
+
+def test_router_level_dep_scope_function() -> None:
+ response = client.get("/router-scope-function/")
+ assert response.status_code == 503
+ assert response.json() == {"detail": "Exception after yield"}
+
+
+def test_router_level_dep_scope_request() -> None:
+ with TestClient(app, raise_server_exceptions=False) as client:
+ response = client.get("/router-scope-request/")
+ assert response.status_code == 200
+ assert response.json() == {"status": "ok"}
+
+
+def test_app_level_dep_scope_function() -> None:
+ app = FastAPI(dependencies=[Depends(raise_after_yield, scope="function")])
+
+ @app.get("/app-scope-function")
+ def get_app_scope_function():
+ return {"status": "ok"}
+
+ with TestClient(app) as client:
+ response = client.get("/app-scope-function")
+ assert response.status_code == 503
+ assert response.json() == {"detail": "Exception after yield"}
+
+
+def test_app_level_dep_scope_request() -> None:
+ app = FastAPI(dependencies=[Depends(raise_after_yield, scope="request")])
+
+ @app.get("/app-scope-request")
+ def get_app_scope_request():
+ return {"status": "ok"}
+
+ with TestClient(app, raise_server_exceptions=False) as client:
+ response = client.get("/app-scope-request")
+ assert response.status_code == 200
+ assert response.json() == {"status": "ok"}