From 1ed5856db0d70e03f6768446586ffdc0bcda06b1 Mon Sep 17 00:00:00 2001 From: John Lancaster <32917998+jsl12@users.noreply.github.com> Date: Thu, 30 Jul 2026 20:51:16 -0500 Subject: [PATCH] asyncgenerator fix --- docs/skills/async-fastapi-sqlmodel/SKILL.md | 6 +++--- .../skills/async-fastapi-sqlmodel/references/engine.md | 4 ++-- .../async-fastapi-sqlmodel/references/session.md | 10 +++++----- .../async-fastapi-sqlmodel/references/testing.md | 8 ++++---- .../nicegui/references/fastapi-uvicorn-startup.md | 4 ++-- tests/web/conftest.py | 6 +++--- 6 files changed, 19 insertions(+), 19 deletions(-) diff --git a/docs/skills/async-fastapi-sqlmodel/SKILL.md b/docs/skills/async-fastapi-sqlmodel/SKILL.md index 2bcfbe7..14db81a 100644 --- a/docs/skills/async-fastapi-sqlmodel/SKILL.md +++ b/docs/skills/async-fastapi-sqlmodel/SKILL.md @@ -139,14 +139,14 @@ This example shows the ownership boundaries. Adapt state storage and dependency ```python from contextlib import AsyncExitStack, asynccontextmanager -from collections.abc import AsyncIterator +from collections.abc import AsyncGeneratorr from fastapi import FastAPI from sqlalchemy.ext.asyncio import async_sessionmaker, create_async_engine from sqlmodel.ext.asyncio.session import AsyncSession @asynccontextmanager -async def lifespan(app: FastAPI) -> AsyncIterator[None]: +async def lifespan(app: FastAPI) -> AsyncGenerator[None]: async with AsyncExitStack() as stack: engine = create_async_engine(settings.database_url) stack.push_async_callback(engine.dispose) @@ -160,7 +160,7 @@ async def lifespan(app: FastAPI) -> AsyncIterator[None]: yield -async def get_session() -> AsyncIterator[AsyncSession]: +async def get_session() -> AsyncGenerator[AsyncSession]: async with app.state.session_factory() as session: yield session ``` diff --git a/docs/skills/async-fastapi-sqlmodel/references/engine.md b/docs/skills/async-fastapi-sqlmodel/references/engine.md index 1d16f1c..3f4a468 100644 --- a/docs/skills/async-fastapi-sqlmodel/references/engine.md +++ b/docs/skills/async-fastapi-sqlmodel/references/engine.md @@ -64,14 +64,14 @@ Resolve settings at the composition boundary and call `get_engine(settings.datab The lifespan context manager only connects the cached resource to FastAPI ownership: ```python -from collections.abc import AsyncIterator +from collections.abc import AsyncGeneratorr from contextlib import asynccontextmanager from fastapi import FastAPI @asynccontextmanager -async def lifespan(app: FastAPI) -> AsyncIterator[None]: +async def lifespan(app: FastAPI) -> AsyncGenerator[None]: database_url = app.state.settings.database_url engine = get_engine(database_url) app.state.engine = engine diff --git a/docs/skills/async-fastapi-sqlmodel/references/session.md b/docs/skills/async-fastapi-sqlmodel/references/session.md index 3f5b799..ea0f3b0 100644 --- a/docs/skills/async-fastapi-sqlmodel/references/session.md +++ b/docs/skills/async-fastapi-sqlmodel/references/session.md @@ -130,7 +130,7 @@ Otherwise, a later call can return a maker that still references the old engine A small [`asynccontextmanager`](https://docs.python.org/3/library/contextlib.html#contextlib.asynccontextmanager) can make repository methods composable. It borrows an existing session when supplied; otherwise it creates and closes one from a supplied factory: ```python -from collections.abc import AsyncIterator +from collections.abc import AsyncGeneratorr from contextlib import asynccontextmanager @@ -139,7 +139,7 @@ async def session_scope( *, database_url: str, session: AsyncSession | None = None, -) -> AsyncIterator[AsyncSession]: +) -> AsyncGenerator[AsyncSession]: if session is not None: yield session return @@ -172,7 +172,7 @@ async def transaction_scope( *, database_url: str, session: AsyncSession | None = None, -) -> AsyncIterator[AsyncSession]: +) -> AsyncGenerator[AsyncSession]: if session is not None: if not session.in_transaction(): raise RuntimeError("A supplied session must have an active transaction") @@ -277,7 +277,7 @@ This preserves atomicity without making repository objects hold mutable `AsyncSe ## Canonical FastAPI Dependency Pattern ```python -from collections.abc import AsyncIterator +from collections.abc import AsyncGenerator from fastapi import Depends from fastapi import Request @@ -294,7 +294,7 @@ def resolve_session_factory(request: Request) -> SessionFactory: async def get_db_session( session_factory: SessionFactory = Depends(resolve_session_factory), -) -> AsyncIterator[AsyncSession]: +) -> AsyncGenerator[AsyncSession]: async with session_factory() as session: yield session ``` diff --git a/docs/skills/async-fastapi-sqlmodel/references/testing.md b/docs/skills/async-fastapi-sqlmodel/references/testing.md index 0f3b6f8..3a6d2e9 100644 --- a/docs/skills/async-fastapi-sqlmodel/references/testing.md +++ b/docs/skills/async-fastapi-sqlmodel/references/testing.md @@ -42,7 +42,7 @@ Use migrations to provision an integration database when migrations are part of For tests that exercise code which calls `commit()`, start an outer transaction on one test connection. Bind the test `AsyncSession` to that connection and use `join_transaction_mode="create_savepoint"`. SQLAlchemy documents this as its test-suite pattern: session commits resolve a SAVEPOINT while fixture teardown rolls back the outer transaction. ```python -from collections.abc import AsyncIterator +from collections.abc import AsyncGeneratorr import pytest_asyncio from sqlalchemy.ext.asyncio import AsyncEngine @@ -50,7 +50,7 @@ from sqlmodel.ext.asyncio.session import AsyncSession @pytest_asyncio.fixture -async def session(test_engine: AsyncEngine) -> AsyncIterator[AsyncSession]: +async def session(test_engine: AsyncEngine) -> AsyncGenerator[AsyncSession]: async with test_engine.connect() as connection: transaction = await connection.begin() test_session = AsyncSession( @@ -78,7 +78,7 @@ def app_with_test_session( app: FastAPI, session: AsyncSession, ) -> FastAPI: - async def get_test_session() -> AsyncIterator[AsyncSession]: + async def get_test_session() -> AsyncGenerator[AsyncSession]: yield session app.dependency_overrides[get_session] = get_test_session @@ -104,7 +104,7 @@ from sqlalchemy.ext.asyncio import AsyncEngine @pytest_asyncio.fixture -async def test_engine() -> AsyncIterator[AsyncEngine]: +async def test_engine() -> AsyncGenerator[AsyncEngine]: engine, _ = create_database("sqlite+aiosqlite://") async with engine.begin() as connection: await connection.run_sync(SQLModel.metadata.create_all) diff --git a/docs/skills/nicegui/references/fastapi-uvicorn-startup.md b/docs/skills/nicegui/references/fastapi-uvicorn-startup.md index 7348191..5cf7abf 100644 --- a/docs/skills/nicegui/references/fastapi-uvicorn-startup.md +++ b/docs/skills/nicegui/references/fastapi-uvicorn-startup.md @@ -126,7 +126,7 @@ def get_settings() -> Settings: The argument-free [`functools.cache`](https://docs.python.org/3/library/functools.html#functools.cache) provider is appropriate here because both the project entry point and Uvicorn's zero-argument factory need process-lifetime access. Each reload or worker process gets its own settings instance. Do not add override arguments to `get_settings()`; inject a `Settings` instance directly into `create_app()` in tests or alternate composition roots. See the [Pydantic settings implementation guide](../../pydantic-settings/SKILL.md) for source precedence, independent settings boundaries, cache clearing, and runtime reload guidance. ```python title="src/my_app/main.py" -from collections.abc import AsyncIterator +from collections.abc import AsyncGeneratorr from contextlib import asynccontextmanager import uvicorn @@ -137,7 +137,7 @@ from my_app.config import Settings, get_settings @asynccontextmanager -async def lifespan(app: FastAPI) -> AsyncIterator[None]: +async def lifespan(app: FastAPI) -> AsyncGenerator[None]: app.state.ready = True try: yield diff --git a/tests/web/conftest.py b/tests/web/conftest.py index 0e3d4b2..218254c 100644 --- a/tests/web/conftest.py +++ b/tests/web/conftest.py @@ -1,6 +1,6 @@ from __future__ import annotations -from collections.abc import AsyncIterator +from collections.abc import AsyncGenerator from contextlib import asynccontextmanager import pytest @@ -14,7 +14,7 @@ from personal_mcp.web.app import create_app @pytest_asyncio.fixture -async def client() -> AsyncIterator[AsyncClient]: +async def client() -> AsyncGenerator[AsyncClient]: """Provides an AsyncClient bound to a fresh application instance.""" app = create_app() async with AsyncClient( @@ -30,7 +30,7 @@ def mcp_session_factory(): """Provides an in-process context manager factory for MCP SDK sessions.""" @asynccontextmanager - async def create_session(*, initialize: bool = True) -> AsyncIterator[ClientSession]: + async def create_session(*, initialize: bool = True) -> AsyncGenerator[ClientSession]: app = create_app() mcp_url = f"http://testserver{app.state.settings.mounts.mcp}" async with (