illagrenan / django-asgi-lifespan

Django ASGI handler with Lifespan Protocol support.
https://illagrenan.github.io/django-asgi-lifespan/
MIT License
10 stars 2 forks source link

Wrong typing? #99

Open pySilver opened 5 days ago

pySilver commented 5 days ago

Following tutorial I saw that Pyright complains about typing. Indeed types are little different in runtime.

from django.apps import AppConfig
from django_asgi_lifespan.register import register_lifespan_manager

from config.context import lifespan_manager

class CoreConfig(AppConfig):
    name = "project.core"

    def ready(self):
        register_lifespan_manager(context_manager=lifespan_manager)  # <-- here is the breakpoint

lifespan_manager is a simple callable up until it is called:

type(lifespan_manager)
PyDev console: using IPython 8.26.0
Out[1]: function
type(lifespan_manager())
Out[2]: contextlib._AsyncGeneratorContextManager
illagrenan commented 4 days ago

Thanks for the report. Could you please send me the error that Pyright is reporting? Thanks!

pySilver commented 3 days ago

@illagrenan here is my context.py which is slightly different than one in your examples (since we return generator, not a mapping) in fact:

from collections.abc import AsyncGenerator
from contextlib import asynccontextmanager
from typing import TYPE_CHECKING

import aiohttp

if TYPE_CHECKING:
    from django_asgi_lifespan.types import State

@asynccontextmanager
async def lifespan_manager() -> AsyncGenerator["State", None]:
    state: State = {
        "aiohttp_client": aiohttp.ClientSession(),
    }

    try:
        yield state
    finally:
        await state["aiohttp_client"].close()

and here is my apps.py:

from django.apps import AppConfig
from django_asgi_lifespan.register import register_lifespan_manager

from config.context import lifespan_manager

class CoreConfig(AppConfig):
    name = "mybaze.core"

    def ready(self):
        register_lifespan_manager(
            context_manager=lifespan_manager,  # pyright: ignore [reportArgumentType] # https://github.com/illagrenan/django-asgi-lifespan/issues/99
        )

Here is full error without suppression: Argument of type "() -> _AsyncGeneratorContextManager[State]" cannot be assigned to parameter "context_manager" of type "LifespanManager" in function "register_lifespan_manager"   "function" is incompatible with protocol "AsyncContextManager[MutableMapping[str, Any]]"     "__aenter__" is not present     "__aexit__" is not present Pyright (reportArgumentType)

P.s. Take my words with grain of salt - I'm not very experienced with complex type hinting in python yet.