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

Added Python 3.5 “async for” compat to websocket #543

Merged
merged 1 commit into from
Oct 24, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@ -415,19 +415,17 @@ using response's methods:
ws = web.WebSocketResponse()
await ws.prepare(request)

while not ws.closed:
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
50 changes: 50 additions & 0 deletions tests/test_py35/test_web_websocket_35.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)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do you need private attribute access. The test may use send() and receive() client response methods.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

eh, no idea, i copied stuff from elsewhere. what methods are you referring to?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

resp._writer.send(item) ?
I think he means _writer is a private attribute and should not be used in testing.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sure. my question is what i should use instead

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

msg = await resp._reader.read()
assert msg.tp == websocket.MSG_TEXT
assert item + '/answer' == msg.data

resp._writer.close()

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

await closed
await resp.close()