Comments (10)
Released in 2.1.0 👍 https://pypi.org/project/asgi-lifespan/2.1.0 Thanks all!
from asgi-lifespan.
I can reproduce with this script. The key is the lifespan
context manager yielding a dict. I don't think this used to be possible. I'm assuming Starlette now does something special with the yielded value. Is there any documentation on this? (Starlette docs, ASGI spec docs…)
Edit: oh, I see it has been standardized. I remember @Kludex's PR on asgiref
now! https://asgi.readthedocs.io/en/latest/specs/lifespan.html?highlight=state#lifespan-state I understand this should then be a feature request for "Support for scope["state"]
".
import asyncio
import httpx
from contextlib import asynccontextmanager
from starlette.applications import Starlette
from asgi_lifespan import LifespanManager
@asynccontextmanager
async def lifespan(app):
print("startup")
yield {"db": "my database connection"}
print("shutdown")
app = Starlette(lifespan=lifespan)
async def main():
async with LifespanManager(app):
print("lifespan ok")
asyncio.run(main())
Output:
startup
Traceback (most recent call last):
File "<frozen runpy>", line 198, in _run_module_as_main
File "<frozen runpy>", line 88, in _run_code
File "/Users/florimond/Desktop/main.py", line 23, in <module>
asyncio.run(main())
File "/Users/florimond/.pyenv/versions/3.11.0/lib/python3.11/asyncio/runners.py", line 190, in run
return runner.run(main)
^^^^^^^^^^^^^^^^
File "/Users/florimond/.pyenv/versions/3.11.0/lib/python3.11/asyncio/runners.py", line 118, in run
return self._loop.run_until_complete(task)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/florimond/.pyenv/versions/3.11.0/lib/python3.11/asyncio/base_events.py", line 650, in run_until_complete
return future.result()
^^^^^^^^^^^^^^^
File "/Users/florimond/Desktop/main.py", line 19, in main
async with LifespanManager(app):
File "/Users/florimond/.pyenv/versions/3.11.0/lib/python3.11/site-packages/asgi_lifespan/_manager.py", line 92, in __aenter__
await self._exit_stack.aclose()
File "/Users/florimond/.pyenv/versions/3.11.0/lib/python3.11/contextlib.py", line 672, in aclose
await self.__aexit__(None, None, None)
File "/Users/florimond/.pyenv/versions/3.11.0/lib/python3.11/contextlib.py", line 730, in __aexit__
raise exc_details[1]
File "/Users/florimond/.pyenv/versions/3.11.0/lib/python3.11/contextlib.py", line 713, in __aexit__
cb_suppress = await cb(*exc_details)
^^^^^^^^^^^^^^^^^^^^^^
File "/Users/florimond/.pyenv/versions/3.11.0/lib/python3.11/site-packages/asgi_lifespan/_concurrency/asyncio.py", line 80, in __aexit__
await self.task
File "/Users/florimond/.pyenv/versions/3.11.0/lib/python3.11/site-packages/asgi_lifespan/_concurrency/asyncio.py", line 63, in run_and_silence_cancelled
await self.coroutine()
File "/Users/florimond/.pyenv/versions/3.11.0/lib/python3.11/site-packages/asgi_lifespan/_manager.py", line 64, in run_app
await self.app(scope, self.receive, self.send)
File "/Users/florimond/.pyenv/versions/3.11.0/lib/python3.11/site-packages/starlette/applications.py", line 120, in __call__
await self.middleware_stack(scope, receive, send)
File "/Users/florimond/.pyenv/versions/3.11.0/lib/python3.11/site-packages/starlette/middleware/errors.py", line 149, in __call__
await self.app(scope, receive, send)
File "/Users/florimond/.pyenv/versions/3.11.0/lib/python3.11/site-packages/starlette/middleware/exceptions.py", line 55, in __call__
await self.app(scope, receive, send)
File "/Users/florimond/.pyenv/versions/3.11.0/lib/python3.11/site-packages/starlette/routing.py", line 705, in __call__
await self.lifespan(scope, receive, send)
File "/Users/florimond/.pyenv/versions/3.11.0/lib/python3.11/contextlib.py", line 222, in __aexit__
await self.gen.athrow(typ, value, traceback)
File "/Users/florimond/Desktop/main.py", line 11, in lifespan
yield {"db": "my database connection"}
File "/Users/florimond/.pyenv/versions/3.11.0/lib/python3.11/site-packages/starlette/routing.py", line 678, in lifespan
raise RuntimeError(
RuntimeError: The server does not support "state" in the lifespan scope.
from asgi-lifespan.
My understanding of the spec is that asgi-lifespan
(acting as an in-process / in-memory server) should ensure that ASGI scopes get a shallow copy of this dict.
https://asgi.readthedocs.io/en/latest/specs/lifespan.html#lifespan-state
The server will ensure that a shallow copy of the namespace is passed into each subsequent request/response call into the application.
I believe this implies storing some kind of per-instance dict on LifespanManager
instances, and passing (copying?) it when building the {"type": "lifespan"}
scope?
I don't have the full view over the details, though, so happy to review PRs that add support for this. Greetings!
from asgi-lifespan.
@GuillaumeDesforges Would you like to try out #59 before we merge?
pip install "git+https://github.com/euri10/asgi-lifespan.git@c2cf923146b03d9b04da29bf256fe90cea981527"
from asgi-lifespan.
@GuillaumeDesforges Thanks for the reproduction repo.
On lines 10 and 11 here: https://github.com/GuillaumeDesforges/reproduce-asgi-lifespan-57/blob/master/tests/test_app.py#L10
You’d now need to do as shown in the updated README: https://github.com/florimondmanca/asgi-lifespan/pull/59/files#diff-b335630551682c19a781afebcf4d07bf978fb1f8ac04c6bf87428ed5106870f5R139
i.e. pass app=manager.app
to AsyncClient
How do things look with that tweak?
from asgi-lifespan.
It works 👌
from asgi-lifespan.
was making the switch fron on_startup/on_shutdown to lifespan on some apps today and about to report the same @florimondmanca
from asgi-lifespan.
Hi there,
I understand something changed in the scope
that Starlette expects, namely that there'd be some "state"
key for it to use? Is it a standard ASGI thing, or is it something we happen to drop / not include but should?
from asgi-lifespan.
There's a new section on Starlette: https://www.starlette.io/lifespan/
from asgi-lifespan.
Did not work for me. See https://github.com/GuillaumeDesforges/reproduce-asgi-lifespan-57
from asgi-lifespan.
Related Issues (17)
- Usage examples should be tested
- Testing use case guide HOT 3
- Can't use LifespanManager with pytest-asyncio HOT 2
- Remove dependency on anyio?
- Switch to register-on-init style for Lifespan event handlers
- Enforcing top-level imports
- Should we get rid of `Lifespan` and `LifespanMiddleware`? HOT 8
- Implement lifespan manager
- Rationale for strong dependency on starlette 0.13? HOT 4
- Implement lifespan middleware
- Handling `lifespan.shutdown.failed` ASGI messages HOT 1
- [feature request] support ContextVars HOT 9
- Test fail on FreeBSD HOT 1
- Error reproducing an example from the REAME.md HOT 3
- Implement lifespan app
- Failing tests: 'lifespan.startup' != 'http.request'
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from asgi-lifespan.