{"id":24013685,"url":"https://github.com/abhiaagarwal/asgi-sqlalchemy","last_synced_at":"2026-02-04T02:05:15.069Z","repository":{"id":270712878,"uuid":"911023450","full_name":"abhiaagarwal/asgi-sqlalchemy","owner":"abhiaagarwal","description":"ASGI Middleware that manages the lifespan of a database request","archived":false,"fork":false,"pushed_at":"2025-01-02T16:08:08.000Z","size":43,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-02-08T08:48:21.344Z","etag":null,"topics":["asgi","fastapi","python","sqlalchemy"],"latest_commit_sha":null,"homepage":"https://pypi.org/project/asgi-sqlalchemy/","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/abhiaagarwal.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2025-01-02T04:24:48.000Z","updated_at":"2025-01-07T02:34:09.000Z","dependencies_parsed_at":"2025-01-02T16:15:21.321Z","dependency_job_id":"d511f6f8-ac7a-4b94-8d5f-fdfa8529455e","html_url":"https://github.com/abhiaagarwal/asgi-sqlalchemy","commit_stats":null,"previous_names":["abhiaagarwal/asgi-sqlalchemy"],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/abhiaagarwal%2Fasgi-sqlalchemy","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/abhiaagarwal%2Fasgi-sqlalchemy/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/abhiaagarwal%2Fasgi-sqlalchemy/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/abhiaagarwal%2Fasgi-sqlalchemy/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/abhiaagarwal","download_url":"https://codeload.github.com/abhiaagarwal/asgi-sqlalchemy/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":240710049,"owners_count":19845039,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["asgi","fastapi","python","sqlalchemy"],"created_at":"2025-01-08T06:56:54.477Z","updated_at":"2026-02-04T02:05:15.061Z","avatar_url":"https://github.com/abhiaagarwal.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# asgi-sqlalchemy\n\nASGI Middleware that manages the lifespan of a database engine and a corresponding session, featuring no global state, and automatic rollbacks on unhandled exceptions. Includes FastAPI and Starlette integrations.\n\nI wrote about my motivations for this library in-depth [here](https://abhi.rodeo/posts/programming/languages/python/fastapi/globals-in-fastapi/), but the short version is that using the ASGI lifespan protocol, we can avoid the use of global state, making database access more predictable and easier to test/mock.\n\n## Installation:\n\n```bash\nuv add asgi-sqlalchemy\n```\n\n## Usage:\n\n### FastAPI:\n\n```python\nfrom contextlib import AsyncContextManager\nfrom collections.abc import AsyncGenerator\nfrom typing_extensions import TypedDict\n\nfrom fastapi import FastAPI\n\nfrom asgi_sqlalchemy import DatabaseContext, SessionMiddleware\nfrom asgi_sqlalchemy.fastapi import SessionDependency\n\nclass AppState(TypedDict):\n    db: DatabaseContext\n\nasync def lifespan() -\u003e AsyncGenerator[AppState]:\n    async with DatabaseContext(...) as db:\n        yield {\"db\": db}\n\napp = FastAPI()\napp.add_middleware(SessionMiddleware)\n\n@app.get(\"/db\")\nasync def handler(session: SessionDependency) -\u003e str:\n    # do something with your async session!\n```\n\n### Starlette:\n\n```python\nfrom contextlib import AsyncContextManager\nfrom collections.abc import AsyncGenerator\nfrom typing_extensions import TypedDict\n\nfrom starlette.applications import Starlette\nfrom starlette.requests import Request\nfrom starlette.responses import JSONResponse\nfrom starlette.routing import Route\n\nfrom asgi_sqlalchemy import DatabaseContext, SessionMiddleware\nfrom asgi_sqlalchemy.starlette import get_session\n\nclass AppState(TypedDict):\n    db: DatabaseContext\n\nasync def lifespan() -\u003e AsyncGenerator[AppState]:\n    async with DatabaseContext(...) as db:\n        yield {\"db\": db}\n\nasync def handler(request: Request) -\u003e JSONResponse:\n    session = await get_session(request)\n    # do something with your async session!\n\napp = Starlette(routes=[Route(\"/db\", handler)], lifespan=lifespan)\napp.add_middleware(SessionMiddleware)\n```\n\n### Tests:\n\nThis library was explicitly designed to be easy to test without dependency overrides.\n\n- For synchronous tests, use FastAPI's `TestClient`.\n- For asynchronous tests, use HTTPX `AsyncClient` with `ASGITransport`, and wrap the app with `LifespanManager` so startup/shutdown events run. See the FastAPI docs: [Async Tests – In Detail](https://fastapi.tiangolo.com/advanced/async-tests/?h=lifespanmanager#in-detail).\n- To “mock” your database, provide a custom lifespan in tests that yields the database object you want (real DB or test double). The middleware will inject a fresh session per request, no dependency overrides needed.\n\nSee complete examples in [`tests/test_fastapi.py`](./tests/test_fastapi.py) and [`tests/test_starlette.py`](./tests/test_starlette.py) inside the [`tests/`](./tests/) folder.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fabhiaagarwal%2Fasgi-sqlalchemy","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fabhiaagarwal%2Fasgi-sqlalchemy","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fabhiaagarwal%2Fasgi-sqlalchemy/lists"}