Django channels raises TypeError on close: An asyncio.Future, a coroutine or an awaitable is required

191 views
Skip to first unread message

Rodrigo Bistolfi

unread,
Mar 23, 2019, 1:40:35 PM3/23/19
to Django users
Hi there,

I am using Channels 2.1.7 with Python 3.7.2.
My consumer does this on connect:

async def connect(self):
   
"""Accept connect if user has been provided by middleware"""  
   
self.user = self.scope.get('user')
   
if self.user:
        await
self.accept()
   
else:
        await
self.close()

When `self.close()` is called, an exception is raised:

Traceback (most recent call last):
 
File "/opt/sps/.venv/lib/python3.7/site-packages/uvicorn/protocols/websockets/websockets_impl.py", line 147, in run_asgi
    result
= await asgi(self.asgi_receive, self.asgi_send)
 
File "/opt/sps/.venv/lib/python3.7/site-packages/channels/consumer.py", line 59, in __call__
   
[receive, self.channel_receive], self.dispatch
 
File "/opt/sps/.venv/lib/python3.7/site-packages/channels/utils.py", line 59, in await_many_dispatch
    await task
 
File "/opt/sps/.venv/lib/python3.7/site-packages/channels/utils.py", line 51, in await_many_dispatch
    result
= task.result()
 
File "/opt/sps/.venv/lib/python3.7/site-packages/uvicorn/protocols/websockets/websockets_impl.py", line 227, in asgi_receive
    data
= await self.recv()
 
File "/opt/sps/.venv/lib/python3.7/site-packages/websockets/protocol.py", line 420, in recv
    return_when
=asyncio.FIRST_COMPLETED,
 
File "/usr/local/lib/python3.7/asyncio/tasks.py", line 361, in wait
    fs
= {ensure_future(f, loop=loop) for f in set(fs)}
 
File "/usr/local/lib/python3.7/asyncio/tasks.py", line 361, in <setcomp>
    fs
= {ensure_future(f, loop=loop) for f in set(fs)}
 
File "/usr/local/lib/python3.7/asyncio/tasks.py", line 592, in ensure_future
   
raise TypeError('An asyncio.Future, a coroutine or an awaitable is '
TypeError: An asyncio.Future, a coroutine or an awaitable is required

The relevant code seems to be this:

while len(self.messages) <= 0:
    pop_message_waiter
= asyncio.Future(loop=self.loop)
   
self._pop_message_waiter = pop_message_waiter
   
try:
       
# If asyncio.wait() is canceled, it doesn't cancel
       
# pop_message_waiter and self.transfer_data_task.
        tasks
= [pop_message_waiter, self.transfer_data_task]
       
yield from asyncio.wait(
            tasks
,
            loop
=self.loop,
            return_when
=asyncio.FIRST_COMPLETED,
       
)
   
finally:
       
self._pop_message_waiter = None

In websockets/protocol.py line 410 and ss, `self.trasfer_data_task` is `None`. If I remove it from the wait list it seems to work.
Any ideas?

Thanks in advance, Rodrigo
Reply all
Reply to author
Forward
0 new messages