Skip to content

Commit 3a3893f

Browse files
authored
fix: allow lifespan to receive app=None (#30)
1 parent 065b853 commit 3a3893f

File tree

2 files changed

+17
-11
lines changed

2 files changed

+17
-11
lines changed

src/fastsqla.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import os
33
from collections.abc import AsyncGenerator, Awaitable, Callable, Iterable
44
from contextlib import _AsyncGeneratorContextManager, asynccontextmanager
5-
from typing import Annotated, Generic, TypeVar, TypedDict
5+
from typing import Annotated, Generic, TypedDict, TypeVar
66

77
from fastapi import Depends as BaseDepends
88
from fastapi import FastAPI, Query
@@ -90,7 +90,7 @@ class State(TypedDict):
9090

9191
def new_lifespan(
9292
url: str | None = None, **kw
93-
) -> Callable[[FastAPI], _AsyncGeneratorContextManager[State, None]]:
93+
) -> Callable[[FastAPI | None], _AsyncGeneratorContextManager[State, None]]:
9494
"""Create a new lifespan async context manager.
9595
9696
It expects the exact same parameters as
@@ -117,7 +117,7 @@ def new_lifespan(
117117
has_config = url is not None
118118

119119
@asynccontextmanager
120-
async def lifespan(app: FastAPI) -> AsyncGenerator[State, None]:
120+
async def lifespan(app: FastAPI | None) -> AsyncGenerator[State, None]:
121121
if has_config:
122122
prefix = ""
123123
sqla_config = {**kw, **{"url": url}}

tests/unit/test_lifespan.py

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,23 @@
11
from fastapi import FastAPI
2-
from pytest import raises
2+
from pytest import raises, fixture
33

4-
app = FastAPI()
4+
_app = FastAPI()
55

66

7-
async def test_it_returns_state(environ):
7+
@fixture(params=[_app, None])
8+
def app(request):
9+
# lifespan tests pass whether lifespan receives app or None
10+
return request.param
11+
12+
13+
async def test_it_returns_state(environ, app):
814
from fastsqla import lifespan
915

1016
async with lifespan(app) as state:
1117
assert "fastsqla_engine" in state
1218

1319

14-
async def test_it_binds_an_sqla_engine_to_sessionmaker(environ):
20+
async def test_it_binds_an_sqla_engine_to_sessionmaker(environ, app):
1521
from fastsqla import SessionFactory, lifespan
1622

1723
assert SessionFactory.kw["bind"] is None
@@ -24,7 +30,7 @@ async def test_it_binds_an_sqla_engine_to_sessionmaker(environ):
2430
assert SessionFactory.kw["bind"] is None
2531

2632

27-
async def test_it_fails_on_a_missing_sqlalchemy_url(monkeypatch):
33+
async def test_it_fails_on_a_missing_sqlalchemy_url(monkeypatch, app):
2834
from fastsqla import lifespan
2935

3036
monkeypatch.delenv("SQLALCHEMY_URL", raising=False)
@@ -35,7 +41,7 @@ async def test_it_fails_on_a_missing_sqlalchemy_url(monkeypatch):
3541
assert raise_info.value.args[0] == "Missing sqlalchemy_url in environ."
3642

3743

38-
async def test_it_fails_on_not_async_engine(monkeypatch):
44+
async def test_it_fails_on_not_async_engine(monkeypatch, app):
3945
from fastsqla import lifespan
4046

4147
monkeypatch.setenv("SQLALCHEMY_URL", "sqlite:///:memory:")
@@ -46,7 +52,7 @@ async def test_it_fails_on_not_async_engine(monkeypatch):
4652
assert "'pysqlite' is not async." in raise_info.value.args[0]
4753

4854

49-
async def test_new_lifespan_with_connect_args(sqlalchemy_url):
55+
async def test_new_lifespan_with_connect_args(sqlalchemy_url, app):
5056
from fastsqla import new_lifespan
5157

5258
lifespan = new_lifespan(sqlalchemy_url, connect_args={"autocommit": False})
@@ -55,7 +61,7 @@ async def test_new_lifespan_with_connect_args(sqlalchemy_url):
5561
pass
5662

5763

58-
async def test_new_lifespan_fails_with_invalid_connect_args(sqlalchemy_url):
64+
async def test_new_lifespan_fails_with_invalid_connect_args(sqlalchemy_url, app):
5965
from fastsqla import new_lifespan
6066

6167
lifespan = new_lifespan(sqlalchemy_url, connect_args={"this is wrong": False})

0 commit comments

Comments
 (0)