Coder Social home page Coder Social logo

Comments (10)

florimondmanca avatar florimondmanca commented on July 25, 2024 2

Released in 2.1.0 👍 https://pypi.org/project/asgi-lifespan/2.1.0 Thanks all!

from asgi-lifespan.

florimondmanca avatar florimondmanca commented on July 25, 2024 1

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.

florimondmanca avatar florimondmanca commented on July 25, 2024 1

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.

florimondmanca avatar florimondmanca commented on July 25, 2024 1

@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.

florimondmanca avatar florimondmanca commented on July 25, 2024 1

@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.

GuillaumeDesforges avatar GuillaumeDesforges commented on July 25, 2024 1

It works 👌

from asgi-lifespan.

euri10 avatar euri10 commented on July 25, 2024

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.

florimondmanca avatar florimondmanca commented on July 25, 2024

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.

Kludex avatar Kludex commented on July 25, 2024

There's a new section on Starlette: https://www.starlette.io/lifespan/

from asgi-lifespan.

GuillaumeDesforges avatar GuillaumeDesforges commented on July 25, 2024

Did not work for me. See https://github.com/GuillaumeDesforges/reproduce-asgi-lifespan-57

from asgi-lifespan.

Related Issues (16)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo 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.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.