Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Recent version of channels doesn't support ASGI3 #1319

Closed
Avinash-Raj opened this issue Jul 17, 2019 · 15 comments
Closed

Recent version of channels doesn't support ASGI3 #1319

Avinash-Raj opened this issue Jul 17, 2019 · 15 comments
Labels

Comments

@Avinash-Raj
Copy link

Since the recent version of daphne (2.3.0) added support for ASGI3, I no longer can't use channels (2.2.0).

https://github.com/django/daphne/blob/master/daphne/cli.py#L30

Here it would likely to call channel's router ( ProtocolTypeRouter) with additional two parameters (send, receive) which by now (

def __call__(self, scope):
) is not supported.

Can we have support for ASGI3?

@Avinash-Raj
Copy link
Author

Avinash-Raj commented Jul 17, 2019

As for now, I just created subclass of ProtocolTypeRouter like below to support ASGI3.

from channels.routing import ProtocolTypeRouter


class CustomSocketioProtocolTypeRouter(ProtocolTypeRouter):
    """
    Overrided base class's __call__ method to support python socketio 4.2.0 and daphne 2.3.0
    """
    def __call__(self, scope, *args):
        if scope["type"] in self.application_mapping:
            handlerobj = self.application_mapping[scope["type"]](scope)
            if args:
                return handlerobj(*args)
            return handlerobj
        raise ValueError(
            "No application configured for scope type %r" % scope["type"]
        )

application = CustomSocketioProtocolTypeRouter({
    # (http->django views is added by default)
})

@carltongibson
Copy link
Member

carltongibson commented Jul 17, 2019

This is related to #1316.

Can we have support for ASGI3?

Short answer, yes.

I'm working on an update for Daphne now, and then will be coming back to update Channels.

Any help in the form of PRs towards that would be awesome!

@felocru
Copy link

felocru commented Oct 10, 2019

As for now, I just created subclass of ProtocolTypeRouter like below to support ASGI3.

from channels.routing import ProtocolTypeRouter


class CustomSocketioProtocolTypeRouter(ProtocolTypeRouter):
    """
    Overrided base class's __call__ method to support python socketio 4.2.0 and daphne 2.3.0
    """
    def __call__(self, scope, *args):
        if scope["type"] in self.application_mapping:
            handlerobj = self.application_mapping[scope["type"]](scope)
            if args:
                return handlerobj(*args)
            return handlerobj
        raise ValueError(
            "No application configured for scope type %r" % scope["type"]
        )

application = CustomSocketioProtocolTypeRouter({
    # (http->django views is added by default)
})

Hi, could you share how you solved it? I can't get it to work.

@adamchainz
Copy link
Member

N.B. you should be able to wrap Channels ASGI 2 apps with asgiref.compatibility.guarantee_single_callable - https://github.com/django/asgiref/blob/master/asgiref/compatibility.py#L39 - to convert it to ASGI 3.

@mburke05
Copy link

mburke05 commented Feb 15, 2020

piggybacking on this @adamchainz i tried your solution and wrapped my application in asgi.py using compatibility.guarantee_single_callable(get_asgi_application()) but when i run my app i'm still getting the TypeError: __call__() missing 2 required positional arguments: 'receive' and 'send' implying it's still ASGI3

@adamchainz
Copy link
Member

I think you’re wrapping the wrong app @mburke05 .

@mburke05
Copy link

mburke05 commented Feb 15, 2020

hm, i've tried wrapping:

application = compatibility.guarantee_single_callable( ProtocolTypeRouter({ # (http->django views is added by default) }) ) in routing.py

assuming that's what you mean, but i'm getting the same result. (Django=3.0.2,channels=2.4.0)

just for posterity the full error:

 HTTP GET / 500 [0.00, 172.20.0.1:50300]
Traceback (most recent call last):
File "/usr/local/lib/python3.8/site-packages/daphne/http_protocol.py", line 163, in process
self.application_queue = yield maybeDeferred(
TypeError: new_application() missing 2 required positional arguments: 'receive' and 'send'

edit: fwiw i fixed this it looks like with a fresh install (i think it may have been a result of twisted not behaving with windows 10 but unsure), but i'll leave it in case the app wrapping question gets answered for someone in the future)

@jaydenwindle
Copy link
Contributor

@carltongibson I'd love to help out with this. Any advice for where to start?

@carltongibson
Copy link
Member

Hi @jaydenwindle. Take a look here: https://asgi.readthedocs.io/en/latest/specs/main.html#applications — This explains the change from the double to single callable.

For now we can just wrap our channels apps, as @adamchainz says. First step might be to add a note to that effect to the docs.

But longer term, and this is #1316 too is to migrate everything across to single callable.
It's a bit of a job, because all the consumers will need adjusting, which is why it's still here.
It's in the Nice Project scale for someone (maybe you 🙂).

Maybe we could adjust the various Routers to the new style first, using asgiref.compatibility to embed consumers. Then the consumers and so on.

If you want to take this on, I'd be very happy to support you: we would need to work out a roadmap and document where we were for people adapting, but it should be possible to do it incrementally. And it does need doing.

@carltongibson
Copy link
Member

@jaydenwindle There aren't that many classes. Maybe it makes sense to bump them all at once and do a major version release with a migration guide. That's a bigger chunk of work all at once though...

@jaydenwindle
Copy link
Contributor

@carltongibson Sounds good! I'd love to take this on.

I think it makes sense to release the ASGI 3 changes all at once. I'll raise a couple of PRs for this so it's easier to review. Using asgiref.compatibility should make it easy enough to refactor the different groups (routers, consumers, etc) without too many conflicts. Then we can merge them into a feature branch and do a major version release.

Do we want to add in deprecation warnings for users that are still using the legacy-style double callables?

@carltongibson
Copy link
Member

Do we want to add in deprecation warnings for users that are still using the legacy-style double callables?

Not sure yet. Argh! 🙂 — Start and I'll try it out and see what I need to do to migrate. The difficulty is going to be when we've subclassed the generic consumers. I'm guessing the upgrade steps will be enough of a warning.

@jaydenwindle
Copy link
Contributor

@carltongibson Haha alright, sounds good 🙂

@nihilok
Copy link

nihilok commented Oct 22, 2020

As for now, I just created subclass of ProtocolTypeRouter like below to support ASGI3.

from channels.routing import ProtocolTypeRouter


class CustomSocketioProtocolTypeRouter(ProtocolTypeRouter):
    """
    Overrided base class's __call__ method to support python socketio 4.2.0 and daphne 2.3.0
    """
    def __call__(self, scope, *args):
        if scope["type"] in self.application_mapping:
            handlerobj = self.application_mapping[scope["type"]](scope)
            if args:
                return handlerobj(*args)
            return handlerobj
        raise ValueError(
            "No application configured for scope type %r" % scope["type"]
        )

application = CustomSocketioProtocolTypeRouter({
    # (http->django views is added by default)
})

This worked for me when i had this issue today. I'm following the tutorial on read the docs.

@carltongibson
Copy link
Member

Fixed in Channels v3.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

7 participants