-
-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- add asgi integration - add integration docs
- Loading branch information
Showing
11 changed files
with
246 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
from __future__ import annotations | ||
|
||
from contextlib import suppress | ||
from dataclasses import dataclass | ||
from typing import TYPE_CHECKING, Any, Awaitable, Callable, Dict | ||
|
||
if TYPE_CHECKING: | ||
from edgy.core.Database import Database | ||
|
||
ASGIApp = Callable[ | ||
[ | ||
Dict[str, Any], | ||
Callable[[], Awaitable[Dict[str, Any]]], | ||
Callable[[Dict[str, Any]], Awaitable[None]], | ||
], | ||
Awaitable[None], | ||
] | ||
|
||
|
||
class MuteInteruptException(BaseException): | ||
pass | ||
|
||
|
||
@dataclass | ||
class ASGIHelper: | ||
app: ASGIApp | ||
database: Database | ||
handle_lifespan: bool = False | ||
|
||
async def __call__( | ||
self, | ||
scope: Dict[str, Any], | ||
receive: Callable[[], Awaitable[Dict[str, Any]]], | ||
send: Callable[[Dict[str, Any]], Awaitable[None]], | ||
) -> None: | ||
if scope["type"] == "lifespan": | ||
original_receive = receive | ||
|
||
async def receive() -> Dict[str, Any]: | ||
message = await original_receive() | ||
if message["type"] == "lifespan.startup": | ||
try: | ||
await self.database.connect() | ||
except Exception as exc: | ||
await send({"type": "lifespan.startup.failed", "msg": str(exc)}) | ||
raise MuteInteruptException from None | ||
elif message["type"] == "lifespan.shutdown": | ||
try: | ||
await self.database.disconnect() | ||
except Exception as exc: | ||
await send({"type": "lifespan.shutdown.failed", "msg": str(exc)}) | ||
raise MuteInteruptException from None | ||
return message | ||
|
||
if self.handle_lifespan: | ||
with suppress(MuteInteruptException): | ||
while True: | ||
message = await receive() | ||
if message["type"] == "lifespan.startup": | ||
await send({"type": "lifespan.startup.complete"}) | ||
elif message["type"] == "lifespan.shutdown": | ||
await send({"type": "lifespan.shutdown.complete"}) | ||
return | ||
return | ||
|
||
with suppress(MuteInteruptException): | ||
await self.app(scope, receive, send) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
# Integrations | ||
|
||
Databasez has several ways to integrate in applications. Mainly recommended | ||
are the async contextmanager one and the asgi based. | ||
|
||
## AsyncContextManager | ||
|
||
The recommended way of manually using databasez is via the async contextmanager protocol. | ||
This way it is ensured that the database is tore down on errors. | ||
|
||
Luckily starlette based apps support the lifespan protocol (startup, teardown of an ASGI server) via async contextmanagers. | ||
|
||
```python | ||
{!> ../docs_src/integrations/starlette.py !} | ||
``` | ||
|
||
Note: This works also in different domains which are not web related. | ||
|
||
|
||
## ASGI | ||
|
||
This is a lifespan protocol interception shim for ASGI lifespan. Instead of using the lifespan parameter of starlette, it is possible | ||
to wrap the ASGI application via the shim. This way databasez intercepts lifespans requests and injects its code. | ||
By default it passes the lifespan request further down, but it has a compatibility option named `handle_lifespan`. | ||
It is required for ASGI apps without lifespan support like django. | ||
|
||
|
||
```python | ||
{!> ../docs_src/integrations/django.py !} | ||
``` | ||
|
||
## Manually | ||
|
||
Some Server doesn't support the lifespan protocol. E.g. WSGI based servers. Here is an example how to integrate it. | ||
As well as with the AsyncContextManager we are not limitted to web applications. | ||
|
||
```python | ||
{!> ../docs_src/integrations/esmerald.py !} | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
from django.core.asgi import get_asgi_application | ||
|
||
from databasez import Database | ||
|
||
applications = Database("sqlite:///foo.sqlite").asgi( | ||
# except you have a lifespan handler in django | ||
handle_lifespan=True | ||
)(get_asgi_application()) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
from esmerald import Esmerald | ||
|
||
from databasez import Database | ||
|
||
database = Database("sqlite:///foo.sqlite") | ||
|
||
|
||
app = Esmerald(routes=[]) | ||
|
||
|
||
@app.on_event("startup") | ||
async def startup(): | ||
await database.connect() | ||
|
||
|
||
@app.on_event("shutdown") | ||
async def shutdown(): | ||
await database.disconnect() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import contextlib | ||
|
||
from starlette.applications import Starlette | ||
|
||
from databasez import Database | ||
|
||
database = Database("sqlite:///foo.sqlite") | ||
|
||
|
||
@contextlib.asynccontextmanager | ||
async def lifespan(app): | ||
async with database: | ||
yield | ||
|
||
|
||
application = Starlette( | ||
lifespan=lifespan, | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters