diff --git a/.travis.yml b/.travis.yml index db0eaff937e..a59c60376cc 100644 --- a/.travis.yml +++ b/.travis.yml @@ -63,4 +63,3 @@ deploy: tags: true all_branches: true python: 3.5 - python: 3.6 diff --git a/CHANGES.rst b/CHANGES.rst index 3eac26addf3..09274bfbb40 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -1,9 +1,11 @@ CHANGES ======= -1.3.2 (2017-02-xx) +1.3.2 (2017-02-16) ------------------ +- Awaiting on WebSocketResponse.send_* does not work #1645 + - Fix multiple calls to client ws_connect when using a shared header dict #1643 - Make CookieJar.filter_cookies() accept plain string parameter. #1636 diff --git a/README.rst b/README.rst index 86c28b1c697..70ce9a565ba 100644 --- a/README.rst +++ b/README.rst @@ -72,9 +72,9 @@ This is simple usage example: async for msg in ws: if msg.type == web.MsgType.text: - ws.send_str("Hello, {}".format(msg.data)) + await ws.send_str("Hello, {}".format(msg.data)) elif msg.type == web.MsgType.binary: - ws.send_bytes(msg.data) + await ws.send_bytes(msg.data) elif msg.type == web.MsgType.close: break diff --git a/aiohttp/_ws_impl.py b/aiohttp/_ws_impl.py index ab8a8ed87a0..1fd001c8bc6 100644 --- a/aiohttp/_ws_impl.py +++ b/aiohttp/_ws_impl.py @@ -12,6 +12,7 @@ from struct import Struct from aiohttp import errors, hdrs +from aiohttp.helpers import noop from aiohttp.log import ws_logger __all__ = ('WebSocketParser', 'WebSocketWriter', 'do_handshake', @@ -353,7 +354,7 @@ def _send_frame(self, message, opcode): self._output_size = 0 return self.writer.drain() - return () + return noop() def pong(self, message=b''): """Send pong message.""" diff --git a/aiohttp/helpers.py b/aiohttp/helpers.py index e2520c22c03..645d595ac2a 100644 --- a/aiohttp/helpers.py +++ b/aiohttp/helpers.py @@ -37,12 +37,19 @@ __all__ = ('BasicAuth', 'create_future', 'FormData', 'parse_mimetype', - 'Timeout', 'ensure_future') + 'Timeout', 'ensure_future', 'noop') sentinel = object() Timeout = timeout +if sys.version_info < (3, 5): + noop = tuple +else: + @asyncio.coroutine + def noop(*args, **kwargs): + pass + class BasicAuth(namedtuple('BasicAuth', ['login', 'password', 'encoding'])): """Http basic authentication helper. diff --git a/build-wheels.sh b/build-wheels.sh index 1d0100c7c32..8033defed1c 100755 --- a/build-wheels.sh +++ b/build-wheels.sh @@ -1,5 +1,5 @@ #!/bin/bash -PYTHON_VERSIONS="cp34-cp34m cp35-cp35m" +PYTHON_VERSIONS="cp34-cp34m cp35-cp35m cp36-cp36m" echo "Compile wheels" for PYTHON in ${PYTHON_VERSIONS}; do diff --git a/tests/test_py35/test_client_websocket_35.py b/tests/test_py35/test_client_websocket_35.py index 80e597a2428..4ebd94c631e 100644 --- a/tests/test_py35/test_client_websocket_35.py +++ b/tests/test_py35/test_client_websocket_35.py @@ -54,6 +54,31 @@ async def handler(request): assert ws.closed +async def test_client_ws_async_with_send(loop, test_server): + # send_xxx methods have to return awaitable objects + + async def handler(request): + ws = web.WebSocketResponse() + await ws.prepare(request) + msg = await ws.receive() + ws.send_str(msg.data + '/answer') + await ws.close() + return ws + + app = web.Application(loop=loop) + app.router.add_route('GET', '/', handler) + + server = await test_server(app) + + async with aiohttp.ClientSession(loop=loop) as client: + async with client.ws_connect(server.make_url('/')) as ws: + await ws.send_str('request') + msg = await ws.receive() + assert msg.data == 'request/answer' + + assert ws.closed + + async def test_client_ws_async_with_shortcut(loop, test_server): async def handler(request): diff --git a/tests/test_py35/test_web_websocket_35.py b/tests/test_py35/test_web_websocket_35.py index 9152b6595f1..97b48416e01 100644 --- a/tests/test_py35/test_web_websocket_35.py +++ b/tests/test_py35/test_web_websocket_35.py @@ -12,7 +12,7 @@ async def handler(request): async for msg in ws: assert msg.type == aiohttp.MsgType.TEXT s = msg.data - ws.send_str(s + '/answer') + await ws.send_str(s + '/answer') await ws.close() closed.set_result(1) return ws