Access to app state in CLI plugins #3384
-
Hi! I'm trying to build quite simple CLI plugin similar to flask's shell, that would allow us to easily play around with SQLAlchemy models & queries by using injected I might be completely wrong, but it seems these lifespan hooks are only called within lifespan method of I'm wondering if someone could help me to find out if Here is a simplified implementation of the plugin that injects import asyncio
import sys
from functools import wraps
from click import Group
from litestar import Litestar
from litestar.plugins import CLIPlugin
from sqlalchemy.ext.asyncio import async_sessionmaker
def _make_coroutine(f):
@wraps
def wrapper(*args, **kwargs):
return asyncio.run(f(*args, **kwargs))
return wrapper
class ShellPlugin(CLIPlugin):
def on_cli_init(self, cli: Group) -> None:
@cli.command(name="shell", help="Start IPython repl with async support")
@make_coroutine
async def shell(app: Litestar) -> None:
async with app.lifespan():
session_maker: type[async_sessionmaker] = app.state["session_maker_class"]
await asyncio.gather(
asyncio.to_thread(_start_shell, app=app, session_maker=session_maker)
)
def _start_shell(app: Litestar, session_maker: type[async_sessionmaker]) -> None:
# args accepted by function will be injected by IPython.embed into shell
import IPython
IPython.embed(
using="asyncio",
banner2="The coconut nut is a giant nut; If you eat too much, you'll get very fat",
) Cheers! |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 2 replies
-
The lifespan is only entered by the application in response to the ASGI lifespan startup message from the server, which doesn't happen for cli operations (except Your approach looks reasonable to me. Are you encountering any issues? Another way you can approach it is to have your own lifespan context that is separate from, but called from within the litestar lifespan context. This way you can enter resource contexts separate from the application. |
Beta Was this translation helpful? Give feedback.
Litestar.lifespan()
is documented: https://docs.litestar.dev/2/reference/app.html#litestar.app.Litestar.lifespanThe lifespan is only entered by the application in response to the ASGI lifespan startup message from the server, which doesn't happen for cli operations (except
litestar run
of course).Your approach looks reasonable to me. Are you encountering any issues?
Another way you can approach it is to have your own lifespan context that is separate from, but called from within the litestar lifespan context. This way you can enter resource contexts separate from the application.