Skip to content

Commit

Permalink
Added Python 3.5 “async for” compat to websocket
Browse files Browse the repository at this point in the history
Instead of

while True:
	msg = await ws.receive()
	...
	elif msg.tp == web.MsgType.close:
		break

do:

async for msg in ws:
	...
  • Loading branch information
flying-sheep committed Oct 4, 2015
1 parent 04191d9 commit 48ae89e
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 5 deletions.
14 changes: 14 additions & 0 deletions aiohttp/web_ws.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import sys
import asyncio
import warnings

Expand All @@ -11,6 +12,7 @@

__all__ = ('WebSocketResponse', 'MsgType')

PY_35 = sys.version_info >= (3, 5)

THRESHOLD_CONNLOST_ACCESS = 5

Expand Down Expand Up @@ -285,3 +287,15 @@ def receive_bytes(self):

def write(self, data):
raise RuntimeError("Cannot call .write() for websocket")

if PY_35:
@asyncio.coroutine
def __aiter__(self):
return self

@asyncio.coroutine
def __anext__(self):
msg = yield from self.receive()
if msg.tp == MsgType.close:
raise StopAsyncIteration # NOQA
return msg
8 changes: 3 additions & 5 deletions docs/web.rst
Original file line number Diff line number Diff line change
Expand Up @@ -396,19 +396,17 @@ using response's methods:
ws = web.WebSocketResponse()
await ws.prepare(request)
while True:
msg = await ws.receive()
async for msg in ws:
if msg.tp == aiohttp.MsgType.text:
if msg.data == 'close':
await ws.close()
else:
ws.send_str(msg.data + '/answer')
elif msg.tp == aiohttp.MsgType.close:
print('websocket connection closed')
elif msg.tp == aiohttp.MsgType.error:
print('ws connection closed with exception %s',
ws.exception())
print('websocket connection closed')
return ws
Expand Down
4 changes: 4 additions & 0 deletions tests/test_py35/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
"""
Python 3.5 test module, testing new native async stuff.
This file allows files in here to be called the same as other test files.
"""
50 changes: 50 additions & 0 deletions tests/test_py35/test_web_websocket.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import pytest

import asyncio

from aiohttp import web, websocket
from aiohttp.websocket_client import MsgType, ws_connect


async def create_server(loop, port, method, path, route_handler):
app = web.Application(loop=loop)
app.router.add_route(method, path, route_handler)
handler = app.make_handler(keep_alive_on=False)
return await loop.create_server(handler, '127.0.0.1', port)


@pytest.mark.run_loop
async def test_await(loop, unused_port):
closed = asyncio.Future(loop=loop)

async def handler(request):
ws = web.WebSocketResponse()
await ws.prepare(request)
async for msg in ws:
assert msg.tp == MsgType.text
s = msg.data
ws.send_str(s + '/answer')
await ws.close()
closed.set_result(1)
return ws

port = unused_port()
await create_server(loop, port, 'GET', '/', handler) # returns server
resp = await ws_connect('ws://127.0.0.1:{p}'.format(p=port), loop=loop)

items = ['q1', 'q2', 'q3']
for item in items:
resp._writer.send(item)
msg = await resp._reader.read()
assert msg.tp == websocket.MSG_TEXT
assert item + '/answer' == msg.data

msg = await resp._reader.read()
assert msg.tp == websocket.MSG_CLOSE
assert msg.data == 1000
assert msg.extra == ''

resp._writer.close()

await closed
resp.close()

0 comments on commit 48ae89e

Please sign in to comment.