python-engineio
Advanced tools
+17
-6
@@ -55,4 +55,4 @@ The Engine.IO Client | ||
| @eio.on('disconnect') | ||
| def on_disconnect(): | ||
| print('I'm disconnected!') | ||
| def on_disconnect(reason): | ||
| print('I'm disconnected! reason:', reason) | ||
@@ -67,6 +67,3 @@ For the ``asyncio`` server, event handlers can be regular functions as above, | ||
| The argument given to the ``on`` decorator is the event name. The events that | ||
| are supported are ``connect``, ``message`` and ``disconnect``. Note that the | ||
| ``disconnect`` handler is invoked for application initiated disconnects, | ||
| server initiated disconnects, or accidental disconnects, for example due to | ||
| networking failures. | ||
| are supported are ``connect``, ``message`` and ``disconnect``. | ||
@@ -76,2 +73,16 @@ The ``data`` argument passed to the ``'message'`` event handler contains | ||
| The ``disconnect`` handler is invoked for client initiated disconnects, server | ||
| initiated disconnects, or accidental disconnects, for example due to | ||
| networking failures. The argument passed to this handler provides the | ||
| disconnect reason. Example:: | ||
| @eio.on('disconnect') | ||
| def on_disconnect(reason): | ||
| if reason == eio.reason.CLIENT_DISCONNECT: | ||
| print('client disconnection') | ||
| elif reason == eio.reason.SERVER_DISCONNECT: | ||
| print('the server kicked me out') | ||
| else: | ||
| print(f'disconnect reason: {reason}') | ||
| Connecting to a Server | ||
@@ -78,0 +89,0 @@ ---------------------- |
+0
-1
@@ -1,2 +0,1 @@ | ||
| # -*- coding: utf-8 -*- | ||
| # | ||
@@ -3,0 +2,0 @@ # Configuration file for the Sphinx documentation builder. |
+17
-6
@@ -164,4 +164,4 @@ The Engine.IO Server | ||
| @eio.on('disconnect') | ||
| def on_disconnect(sid): | ||
| print('Client disconnected!') | ||
| def on_disconnect(sid, reason): | ||
| print('Client disconnected! reason:', reason) | ||
@@ -176,6 +176,3 @@ For the ``asyncio`` server, event handlers can be regular functions as above, | ||
| The argument given to the ``on`` decorator is the event name. The events that | ||
| are supported are ``connect``, ``message`` and ``disconnect``. Note that the | ||
| ``disconnect`` handler is invoked for client initiated disconnects, | ||
| server initiated disconnects, or accidental disconnects, for example due to | ||
| networking failures. | ||
| are supported are ``connect``, ``message`` and ``disconnect``. | ||
@@ -197,2 +194,16 @@ The ``sid`` argument passed into all the event handlers is a connection | ||
| The ``disconnect`` handler is invoked for client initiated disconnects, | ||
| server initiated disconnects, or accidental disconnects, for example due to | ||
| networking failures. The second argument passed to this handler provides the | ||
| disconnect reason. Example:: | ||
| @eio.on('disconnect') | ||
| def on_disconnect(sid, reason): | ||
| if reason == eio.reason.CLIENT_DISCONNECT: | ||
| print('the client went away') | ||
| elif reason == eio.reason.SERVER_DISCONNECT: | ||
| print('the client was kicked out') | ||
| else: | ||
| print(f'disconnect reason: {reason}') | ||
| Sending Messages | ||
@@ -199,0 +210,0 @@ ---------------- |
+1
-1
| Metadata-Version: 2.1 | ||
| Name: python-engineio | ||
| Version: 4.10.1 | ||
| Version: 4.11.0 | ||
| Summary: Engine.IO server and client for Python | ||
@@ -5,0 +5,0 @@ Author-email: Miguel Grinberg <miguel.grinberg@gmail.com> |
+5
-1
| [project] | ||
| name = "python-engineio" | ||
| version = "4.10.1" | ||
| version = "4.11.0" | ||
| authors = [{name = "Miguel Grinberg", email = "miguel.grinberg@gmail.com"}] | ||
@@ -44,1 +44,5 @@ description = "Engine.IO server and client for Python" | ||
| build-backend = "setuptools.build_meta" | ||
| [tool.pytest.ini_options] | ||
| asyncio_mode = "auto" | ||
| asyncio_default_fixture_loop_scope = "session" |
@@ -40,3 +40,3 @@ import asyncio | ||
| await asyncio.gather(*tasks, return_exceptions=True) | ||
| asyncio.get_event_loop().stop() | ||
| asyncio.get_running_loop().stop() | ||
@@ -79,2 +79,5 @@ asyncio.ensure_future(_handler()) | ||
| ``aiohttp.ws_connect()``. | ||
| :param timestamp_requests: If ``True`` a timestamp is added to the query | ||
| string of Socket.IO requests as a cache-busting | ||
| measure. Set to ``False`` to disable. | ||
| """ | ||
@@ -111,3 +114,3 @@ def is_asyncio_based(self): | ||
| try: | ||
| asyncio.get_event_loop().add_signal_handler( | ||
| asyncio.get_running_loop().add_signal_handler( | ||
| signal.SIGINT, async_signal_handler) | ||
@@ -155,3 +158,3 @@ except NotImplementedError: # pragma: no cover | ||
| async def disconnect(self, abort=False): | ||
| async def disconnect(self, abort=False, reason=None): | ||
| """Disconnect from the server. | ||
@@ -168,3 +171,5 @@ | ||
| self.state = 'disconnecting' | ||
| await self._trigger_event('disconnect', run_async=False) | ||
| await self._trigger_event('disconnect', | ||
| reason or self.reason.CLIENT_DISCONNECT, | ||
| run_async=False) | ||
| if self.current_transport == 'websocket': | ||
@@ -417,3 +422,4 @@ await self.ws.close() | ||
| elif pkt.packet_type == packet.CLOSE: | ||
| await self.disconnect(abort=True) | ||
| await self.disconnect(abort=True, | ||
| reason=self.reason.SERVER_DISCONNECT) | ||
| elif pkt.packet_type == packet.NOOP: | ||
@@ -471,3 +477,13 @@ pass | ||
| try: | ||
| ret = await self.handlers[event](*args) | ||
| try: | ||
| ret = await self.handlers[event](*args) | ||
| except TypeError: | ||
| print(args, len(args)) | ||
| if event == 'disconnect' and \ | ||
| len(args) == 1: # pragma: no branch | ||
| # legacy disconnect events do not have a reason | ||
| # argument | ||
| return await self.handlers[event]() | ||
| else: # pragma: no cover | ||
| raise | ||
| except asyncio.CancelledError: # pragma: no cover | ||
@@ -492,3 +508,13 @@ pass | ||
| try: | ||
| ret = self.handlers[event](*args) | ||
| try: | ||
| ret = self.handlers[event](*args) | ||
| except TypeError: | ||
| print(args, len(args)) | ||
| if event == 'disconnect' and \ | ||
| len(args) == 1: # pragma: no branch | ||
| # legacy disconnect events do not have a reason | ||
| # argument | ||
| ret = self.handlers[event]() | ||
| else: # pragma: no cover | ||
| raise | ||
| except: | ||
@@ -535,3 +561,4 @@ self.logger.exception(event + ' handler error') | ||
| if self.state == 'connected': | ||
| await self._trigger_event('disconnect', run_async=False) | ||
| await self._trigger_event( | ||
| 'disconnect', self.reason.TRANSPORT_ERROR, run_async=False) | ||
| try: | ||
@@ -590,3 +617,4 @@ base_client.connected_clients.remove(self) | ||
| if self.state == 'connected': | ||
| await self._trigger_event('disconnect', run_async=False) | ||
| await self._trigger_event( | ||
| 'disconnect', self.reason.TRANSPORT_ERROR, run_async=False) | ||
| try: | ||
@@ -593,0 +621,0 @@ base_client.connected_clients.remove(self) |
@@ -28,3 +28,3 @@ import simple_websocket | ||
| except simple_websocket.ConnectionClosed: | ||
| raise IOError() | ||
| raise OSError() | ||
@@ -31,0 +31,0 @@ def wait(self): |
@@ -60,3 +60,3 @@ import asyncio | ||
| if key in environ: | ||
| hdr_value = '%s,%s' % (environ[key], hdr_value) | ||
| hdr_value = f'{environ[key]},{hdr_value}' | ||
@@ -83,3 +83,3 @@ environ[key] = hdr_value | ||
| class WebSocket(object): # pragma: no cover | ||
| class WebSocket: # pragma: no cover | ||
| """ | ||
@@ -119,3 +119,3 @@ This wrapper class provides a aiohttp WebSocket interface that is | ||
| not isinstance(msg.data, str): | ||
| raise IOError() | ||
| raise OSError() | ||
| return msg.data | ||
@@ -122,0 +122,0 @@ |
@@ -138,3 +138,3 @@ import os | ||
| async def translate_request(scope, receive, send): | ||
| class AwaitablePayload(object): # pragma: no cover | ||
| class AwaitablePayload: # pragma: no cover | ||
| def __init__(self, payload): | ||
@@ -165,5 +165,11 @@ self.payload = payload or b'' | ||
| raw_uri = scope['path'].encode('utf-8') | ||
| raw_uri = scope['path'] | ||
| query_string = '' | ||
| if 'query_string' in scope and scope['query_string']: | ||
| raw_uri += b'?' + scope['query_string'] | ||
| try: | ||
| query_string = scope['query_string'].decode('utf-8') | ||
| except UnicodeDecodeError: | ||
| pass | ||
| else: | ||
| raw_uri += '?' + query_string | ||
| environ = { | ||
@@ -180,4 +186,4 @@ 'wsgi.input': AwaitablePayload(payload), | ||
| 'PATH_INFO': scope['path'], | ||
| 'QUERY_STRING': scope.get('query_string', b'').decode('utf-8'), | ||
| 'RAW_URI': raw_uri.decode('utf-8'), | ||
| 'QUERY_STRING': query_string, | ||
| 'RAW_URI': raw_uri, | ||
| 'SCRIPT_NAME': '', | ||
@@ -195,4 +201,8 @@ 'SERVER_PROTOCOL': 'HTTP/1.1', | ||
| for hdr_name, hdr_value in scope['headers']: | ||
| hdr_name = hdr_name.upper().decode('utf-8') | ||
| hdr_value = hdr_value.decode('utf-8') | ||
| try: | ||
| hdr_name = hdr_name.upper().decode('utf-8') | ||
| hdr_value = hdr_value.decode('utf-8') | ||
| except UnicodeDecodeError: | ||
| # skip header if it cannot be decoded | ||
| continue | ||
| if hdr_name == 'CONTENT-TYPE': | ||
@@ -207,3 +217,3 @@ environ['CONTENT_TYPE'] = hdr_value | ||
| if key in environ: | ||
| hdr_value = '%s,%s' % (environ[key], hdr_value) | ||
| hdr_value = f'{environ[key]},{hdr_value}' | ||
@@ -239,3 +249,3 @@ environ[key] = hdr_value | ||
| class WebSocket(object): # pragma: no cover | ||
| class WebSocket: # pragma: no cover | ||
| """ | ||
@@ -278,3 +288,3 @@ This wrapper class provides an asgi WebSocket interface that is | ||
| if event['type'] != 'websocket.receive': | ||
| raise IOError() | ||
| raise OSError() | ||
| return event.get('bytes') or event.get('text') | ||
@@ -281,0 +291,0 @@ |
@@ -1,3 +0,1 @@ | ||
| from __future__ import absolute_import | ||
| from eventlet.green.threading import Event | ||
@@ -4,0 +2,0 @@ from eventlet import queue, sleep, spawn |
@@ -21,3 +21,3 @@ import gevent | ||
| class uWSGIWebSocket(object): # pragma: no cover | ||
| class uWSGIWebSocket: # pragma: no cover | ||
| """ | ||
@@ -119,3 +119,3 @@ This wrapper class provides a uWSGI WebSocket interface that is | ||
| msg = uwsgi.websocket_recv(request_context=self._req_ctx) | ||
| except IOError: # connection closed | ||
| except OSError: # connection closed | ||
| self.close() | ||
@@ -143,3 +143,3 @@ return None | ||
| self._send(msg) | ||
| except IOError: | ||
| except OSError: | ||
| self.close() | ||
@@ -152,3 +152,3 @@ return None | ||
| msg = uwsgi.websocket_recv_nb() | ||
| except IOError: # connection closed | ||
| except OSError: # connection closed | ||
| self.close() | ||
@@ -155,0 +155,0 @@ return None |
@@ -36,3 +36,3 @@ import sys | ||
| """ | ||
| class AwaitablePayload(object): | ||
| class AwaitablePayload: | ||
| def __init__(self, payload): | ||
@@ -82,3 +82,3 @@ self.payload = payload or b'' | ||
| if key in environ: | ||
| hdr_value = '%s,%s' % (environ[key], hdr_value) | ||
| hdr_value = f'{environ[key]},{hdr_value}' | ||
@@ -112,3 +112,3 @@ environ[key] = hdr_value | ||
| class WebSocket(object): # pragma: no cover | ||
| class WebSocket: # pragma: no cover | ||
| """ | ||
@@ -142,3 +142,3 @@ This wrapper class provides a sanic WebSocket interface that is | ||
| not isinstance(data, str): | ||
| raise IOError() | ||
| raise OSError() | ||
| return data | ||
@@ -145,0 +145,0 @@ |
@@ -67,3 +67,3 @@ import asyncio | ||
| """ | ||
| class AwaitablePayload(object): | ||
| class AwaitablePayload: | ||
| def __init__(self, payload): | ||
@@ -146,3 +146,3 @@ self.payload = payload or b'' | ||
| class WebSocket(object): # pragma: no cover | ||
| class WebSocket: # pragma: no cover | ||
| """ | ||
@@ -175,3 +175,3 @@ This wrapper class provides a tornado WebSocket interface that is | ||
| not isinstance(msg, str): | ||
| raise IOError() | ||
| raise OSError() | ||
| return msg | ||
@@ -178,0 +178,0 @@ |
@@ -92,3 +92,3 @@ import asyncio | ||
| engineio_path = engineio_path.strip('/') | ||
| self._async['create_route'](app, self, '/{}/'.format(engineio_path)) | ||
| self._async['create_route'](app, self, f'/{engineio_path}/') | ||
@@ -166,3 +166,3 @@ async def send(self, sid, data): | ||
| """ | ||
| class _session_context_manager(object): | ||
| class _session_context_manager: | ||
| def __init__(self, server, sid): | ||
@@ -197,8 +197,11 @@ self.server = server | ||
| else: | ||
| await socket.close() | ||
| await socket.close(reason=self.reason.SERVER_DISCONNECT) | ||
| if sid in self.sockets: # pragma: no cover | ||
| del self.sockets[sid] | ||
| else: | ||
| await asyncio.wait([asyncio.create_task(client.close()) | ||
| for client in self.sockets.values()]) | ||
| await asyncio.wait([ | ||
| asyncio.create_task(client.close( | ||
| reason=self.reason.SERVER_DISCONNECT)) | ||
| for client in self.sockets.values() | ||
| ]) | ||
| self.sockets = {} | ||
@@ -290,29 +293,37 @@ | ||
| if sid not in self.sockets: | ||
| self._log_error_once('Invalid session ' + sid, 'bad-sid') | ||
| r = self._bad_request('Invalid session ' + sid) | ||
| self._log_error_once(f'Invalid session {sid}', 'bad-sid') | ||
| r = self._bad_request(f'Invalid session {sid}') | ||
| else: | ||
| socket = self._get_socket(sid) | ||
| if self.transport(sid) != transport and \ | ||
| transport != upgrade_header: | ||
| self._log_error_once( | ||
| 'Invalid transport for session ' + sid, | ||
| 'bad-transport') | ||
| r = self._bad_request('Invalid transport') | ||
| try: | ||
| socket = self._get_socket(sid) | ||
| except KeyError as e: # pragma: no cover | ||
| self._log_error_once(f'{e} {sid}', 'bad-sid') | ||
| r = self._bad_request(f'{e} {sid}') | ||
| else: | ||
| try: | ||
| packets = await socket.handle_get_request(environ) | ||
| if isinstance(packets, list): | ||
| r = self._ok(packets, jsonp_index=jsonp_index) | ||
| else: | ||
| r = packets | ||
| except exceptions.EngineIOError: | ||
| if sid in self.sockets: # pragma: no cover | ||
| await self.disconnect(sid) | ||
| r = self._bad_request() | ||
| if sid in self.sockets and self.sockets[sid].closed: | ||
| del self.sockets[sid] | ||
| if self.transport(sid) != transport and \ | ||
| transport != upgrade_header: | ||
| self._log_error_once( | ||
| f'Invalid transport for session {sid}', | ||
| 'bad-transport') | ||
| r = self._bad_request('Invalid transport') | ||
| else: | ||
| try: | ||
| packets = await socket.handle_get_request( | ||
| environ) | ||
| if isinstance(packets, list): | ||
| r = self._ok(packets, | ||
| jsonp_index=jsonp_index) | ||
| else: | ||
| r = packets | ||
| except exceptions.EngineIOError: | ||
| if sid in self.sockets: # pragma: no cover | ||
| await self.disconnect(sid) | ||
| r = self._bad_request() | ||
| if sid in self.sockets and \ | ||
| self.sockets[sid].closed: | ||
| del self.sockets[sid] | ||
| elif method == 'POST': | ||
| if sid is None or sid not in self.sockets: | ||
| self._log_error_once('Invalid session ' + sid, 'bad-sid') | ||
| r = self._bad_request('Invalid session ' + sid) | ||
| self._log_error_once(f'Invalid session {sid}', 'bad-sid') | ||
| r = self._bad_request(f'Invalid session {sid}') | ||
| else: | ||
@@ -447,7 +458,10 @@ socket = self._get_socket(sid) | ||
| pkt = packet.Packet( | ||
| packet.OPEN, {'sid': sid, | ||
| 'upgrades': self._upgrades(sid, transport), | ||
| 'pingTimeout': int(self.ping_timeout * 1000), | ||
| 'pingInterval': int(self.ping_interval * 1000)}) | ||
| pkt = packet.Packet(packet.OPEN, { | ||
| 'sid': sid, | ||
| 'upgrades': self._upgrades(sid, transport), | ||
| 'pingTimeout': int(self.ping_timeout * 1000), | ||
| 'pingInterval': int( | ||
| self.ping_interval + self.ping_interval_grace_period) * 1000, | ||
| 'maxPayload': self.max_http_buffer_size, | ||
| }) | ||
| await s.send(pkt) | ||
@@ -499,3 +513,12 @@ s.schedule_ping() | ||
| try: | ||
| return await self.handlers[event](*args) | ||
| try: | ||
| return await self.handlers[event](*args) | ||
| except TypeError: | ||
| if event == 'disconnect' and \ | ||
| len(args) == 2: # pragma: no branch | ||
| # legacy disconnect events do not have a reason | ||
| # argument | ||
| return await self.handlers[event](args[0]) | ||
| else: # pragma: no cover | ||
| raise | ||
| except asyncio.CancelledError: # pragma: no cover | ||
@@ -519,3 +542,12 @@ pass | ||
| try: | ||
| return self.handlers[event](*args) | ||
| try: | ||
| return self.handlers[event](*args) | ||
| except TypeError: | ||
| if event == 'disconnect' and \ | ||
| len(args) == 2: # pragma: no branch | ||
| # legacy disconnect events do not have a reason | ||
| # argument | ||
| return self.handlers[event](args[0]) | ||
| else: # pragma: no cover | ||
| raise | ||
| except: | ||
@@ -538,2 +570,3 @@ self.logger.exception(event + ' handler error') | ||
| """Monitor connected clients and clean up those that time out.""" | ||
| loop = asyncio.get_running_loop() | ||
| self.service_task_event = self.create_event() | ||
@@ -580,3 +613,3 @@ while not self.service_task_event.is_set(): | ||
| except: | ||
| if asyncio.get_event_loop().is_closed(): | ||
| if loop.is_closed(): | ||
| self.logger.info('event loop is closed, exiting service ' | ||
@@ -583,0 +616,0 @@ 'task') |
@@ -50,3 +50,4 @@ import asyncio | ||
| elif pkt.packet_type == packet.CLOSE: | ||
| await self.close(wait=False, abort=True) | ||
| await self.close(wait=False, abort=True, | ||
| reason=self.server.reason.CLIENT_DISCONNECT) | ||
| else: | ||
@@ -66,3 +67,4 @@ raise exceptions.UnknownPacketError() | ||
| # to their correct state of disconnected | ||
| await self.close(wait=False, abort=False) | ||
| await self.close(wait=False, abort=False, | ||
| reason=self.server.reason.PING_TIMEOUT) | ||
| return False | ||
@@ -100,3 +102,4 @@ return True | ||
| exc = sys.exc_info() | ||
| await self.close(wait=False) | ||
| await self.close(wait=False, | ||
| reason=self.server.reason.TRANSPORT_ERROR) | ||
| raise exc[1].with_traceback(exc[2]) | ||
@@ -116,7 +119,10 @@ return packets | ||
| async def close(self, wait=True, abort=False): | ||
| async def close(self, wait=True, abort=False, reason=None): | ||
| """Close the socket connection.""" | ||
| if not self.closed and not self.closing: | ||
| self.closing = True | ||
| await self.server._trigger_event('disconnect', self.sid) | ||
| await self.server._trigger_event( | ||
| 'disconnect', self.sid, | ||
| reason or self.server.reason.SERVER_DISCONNECT, | ||
| run_async=False) | ||
| if not abort: | ||
@@ -141,3 +147,3 @@ await self.send(packet.Packet(packet.CLOSE)) | ||
| if self.upgraded: | ||
| raise IOError('Socket has been upgraded already') | ||
| raise OSError('Socket has been upgraded already') | ||
| if self.server._async['websocket'] is None: | ||
@@ -164,3 +170,3 @@ # the selected async mode does not support websocket | ||
| pkt = await websocket_wait() | ||
| except IOError: # pragma: no cover | ||
| except OSError: # pragma: no cover | ||
| return | ||
@@ -179,3 +185,3 @@ decoded_pkt = packet.Packet(encoded_packet=pkt) | ||
| pkt = await websocket_wait() | ||
| except IOError: # pragma: no cover | ||
| except OSError: # pragma: no cover | ||
| self.upgrading = False | ||
@@ -261,2 +267,3 @@ return | ||
| await asyncio.wait_for(writer_task, timeout=None) | ||
| await self.close(wait=False, abort=True) | ||
| await self.close(wait=False, abort=True, | ||
| reason=self.server.reason.TRANSPORT_CLOSE) |
@@ -33,5 +33,14 @@ import logging | ||
| class reason: | ||
| """Disconnection reasons.""" | ||
| #: Client-initiated disconnection. | ||
| CLIENT_DISCONNECT = 'client disconnect' | ||
| #: Server-initiated disconnection. | ||
| SERVER_DISCONNECT = 'server disconnect' | ||
| #: Transport error. | ||
| TRANSPORT_ERROR = 'transport error' | ||
| def __init__(self, logger=False, json=None, request_timeout=5, | ||
| http_session=None, ssl_verify=True, handle_sigint=True, | ||
| websocket_extra_options=None): | ||
| websocket_extra_options=None, timestamp_requests=True): | ||
| global original_signal_handler | ||
@@ -60,2 +69,3 @@ if handle_sigint and original_signal_handler is None and \ | ||
| self.websocket_extra_options = websocket_extra_options or {} | ||
| self.timestamp_requests = timestamp_requests | ||
@@ -148,2 +158,4 @@ if json is not None: | ||
| """Generate the Engine.IO query string timestamp.""" | ||
| if not self.timestamp_requests: | ||
| return '' | ||
| return '&t=' + str(time.time()) |
@@ -22,2 +22,15 @@ import base64 | ||
| class reason: | ||
| """Disconnection reasons.""" | ||
| #: Server-initiated disconnection. | ||
| SERVER_DISCONNECT = 'server disconnect' | ||
| #: Client-initiated disconnection. | ||
| CLIENT_DISCONNECT = 'client disconnect' | ||
| #: Ping timeout. | ||
| PING_TIMEOUT = 'ping timeout' | ||
| #: Transport close. | ||
| TRANSPORT_CLOSE = 'transport close' | ||
| #: Transport error. | ||
| TRANSPORT_ERROR = 'transport error' | ||
| def __init__(self, async_mode=None, ping_interval=25, ping_timeout=20, | ||
@@ -24,0 +37,0 @@ max_http_buffer_size=1000000, allow_upgrades=True, |
@@ -1,2 +0,1 @@ | ||
| class BaseSocket: | ||
@@ -3,0 +2,0 @@ upgrade_protocols = ['websocket'] |
@@ -58,2 +58,5 @@ from base64 import b64encode | ||
| ``websocket.create_connection()``. | ||
| :param timestamp_requests: If ``True`` a timestamp is added to the query | ||
| string of Socket.IO requests as a cache-busting | ||
| measure. Set to ``False`` to disable. | ||
| """ | ||
@@ -114,3 +117,3 @@ def connect(self, url, headers=None, transports=None, | ||
| def disconnect(self, abort=False): | ||
| def disconnect(self, abort=False, reason=None): | ||
| """Disconnect from the server. | ||
@@ -125,3 +128,5 @@ | ||
| self.state = 'disconnecting' | ||
| self._trigger_event('disconnect', run_async=False) | ||
| self._trigger_event('disconnect', | ||
| reason or self.reason.CLIENT_DISCONNECT, | ||
| run_async=False) | ||
| if self.current_transport == 'websocket': | ||
@@ -257,3 +262,3 @@ self.ws.close() | ||
| # cookies | ||
| cookies = '; '.join(["{}={}".format(cookie.name, cookie.value) | ||
| cookies = '; '.join([f"{cookie.name}={cookie.value}" | ||
| for cookie in self.http.cookies]) | ||
@@ -332,3 +337,3 @@ for header, value in headers.items(): | ||
| websocket_url + self._get_url_timestamp(), **extra_options) | ||
| except (ConnectionError, IOError, websocket.WebSocketException): | ||
| except (ConnectionError, OSError, websocket.WebSocketException): | ||
| if upgrade: | ||
@@ -412,3 +417,3 @@ self.logger.warning( | ||
| elif pkt.packet_type == packet.CLOSE: | ||
| self.disconnect(abort=True) | ||
| self.disconnect(abort=True, reason=self.reason.SERVER_DISCONNECT) | ||
| elif pkt.packet_type == packet.NOOP: | ||
@@ -453,3 +458,12 @@ pass | ||
| try: | ||
| return self.handlers[event](*args) | ||
| try: | ||
| return self.handlers[event](*args) | ||
| except TypeError: | ||
| if event == 'disconnect' and \ | ||
| len(args) == 1: # pragma: no branch | ||
| # legacy disconnect events do not have a reason | ||
| # argument | ||
| return self.handlers[event]() | ||
| else: # pragma: no cover | ||
| raise | ||
| except: | ||
@@ -490,3 +504,4 @@ self.logger.exception(event + ' handler error') | ||
| if self.state == 'connected': | ||
| self._trigger_event('disconnect', run_async=False) | ||
| self._trigger_event('disconnect', self.reason.TRANSPORT_ERROR, | ||
| run_async=False) | ||
| try: | ||
@@ -541,3 +556,4 @@ base_client.connected_clients.remove(self) | ||
| if self.state == 'connected': | ||
| self._trigger_event('disconnect', run_async=False) | ||
| self._trigger_event('disconnect', self.reason.TRANSPORT_ERROR, | ||
| run_async=False) | ||
| try: | ||
@@ -544,0 +560,0 @@ base_client.connected_clients.remove(self) |
@@ -5,3 +5,3 @@ import os | ||
| class WSGIApp(object): | ||
| class WSGIApp: | ||
| """WSGI application middleware for Engine.IO. | ||
@@ -54,3 +54,3 @@ | ||
| # copy the socket to the eventlet format. | ||
| class Input(object): | ||
| class Input: | ||
| def __init__(self, socket): | ||
@@ -57,0 +57,0 @@ self.socket = socket |
@@ -10,3 +10,3 @@ import base64 | ||
| class Packet(object): | ||
| class Packet: | ||
| """Engine.IO packet.""" | ||
@@ -13,0 +13,0 @@ |
@@ -6,3 +6,3 @@ import urllib | ||
| class Payload(object): | ||
| class Payload: | ||
| """Engine.IO payload.""" | ||
@@ -9,0 +9,0 @@ max_decode_packets = 16 |
+47
-30
@@ -151,3 +151,3 @@ import logging | ||
| """ | ||
| class _session_context_manager(object): | ||
| class _session_context_manager: | ||
| def __init__(self, server, sid): | ||
@@ -180,3 +180,3 @@ self.server = server | ||
| else: | ||
| socket.close() | ||
| socket.close(reason=self.reason.SERVER_DISCONNECT) | ||
| if sid in self.sockets: # pragma: no cover | ||
@@ -186,3 +186,3 @@ del self.sockets[sid] | ||
| for client in self.sockets.copy().values(): | ||
| client.close() | ||
| client.close(reason=self.reason.SERVER_DISCONNECT) | ||
| self.sockets = {} | ||
@@ -272,31 +272,37 @@ | ||
| if sid not in self.sockets: | ||
| self._log_error_once('Invalid session ' + sid, 'bad-sid') | ||
| r = self._bad_request('Invalid session') | ||
| self._log_error_once(f'Invalid session {sid}', 'bad-sid') | ||
| r = self._bad_request(f'Invalid session {sid}') | ||
| else: | ||
| socket = self._get_socket(sid) | ||
| if self.transport(sid) != transport and \ | ||
| transport != upgrade_header: | ||
| self._log_error_once( | ||
| 'Invalid transport for session ' + sid, | ||
| 'bad-transport') | ||
| r = self._bad_request('Invalid transport') | ||
| try: | ||
| socket = self._get_socket(sid) | ||
| except KeyError as e: # pragma: no cover | ||
| self._log_error_once(f'{e} {sid}', 'bad-sid') | ||
| r = self._bad_request(f'{e} {sid}') | ||
| else: | ||
| try: | ||
| packets = socket.handle_get_request( | ||
| environ, start_response) | ||
| if isinstance(packets, list): | ||
| r = self._ok(packets, jsonp_index=jsonp_index) | ||
| else: | ||
| r = packets | ||
| except exceptions.EngineIOError: | ||
| if sid in self.sockets: # pragma: no cover | ||
| self.disconnect(sid) | ||
| r = self._bad_request() | ||
| if sid in self.sockets and self.sockets[sid].closed: | ||
| del self.sockets[sid] | ||
| if self.transport(sid) != transport and \ | ||
| transport != upgrade_header: | ||
| self._log_error_once( | ||
| f'Invalid transport for session {sid}', | ||
| 'bad-transport') | ||
| r = self._bad_request('Invalid transport') | ||
| else: | ||
| try: | ||
| packets = socket.handle_get_request( | ||
| environ, start_response) | ||
| if isinstance(packets, list): | ||
| r = self._ok(packets, | ||
| jsonp_index=jsonp_index) | ||
| else: | ||
| r = packets | ||
| except exceptions.EngineIOError: | ||
| if sid in self.sockets: # pragma: no cover | ||
| self.disconnect(sid) | ||
| r = self._bad_request() | ||
| if sid in self.sockets and \ | ||
| self.sockets[sid].closed: | ||
| del self.sockets[sid] | ||
| elif method == 'POST': | ||
| if sid is None or sid not in self.sockets: | ||
| self._log_error_once( | ||
| 'Invalid session ' + (sid or 'None'), 'bad-sid') | ||
| r = self._bad_request('Invalid session') | ||
| self._log_error_once(f'Invalid session {sid}', 'bad-sid') | ||
| r = self._bad_request(f'Invalid session {sid}') | ||
| else: | ||
@@ -397,3 +403,5 @@ socket = self._get_socket(sid) | ||
| 'pingInterval': int( | ||
| self.ping_interval + self.ping_interval_grace_period) * 1000}) | ||
| self.ping_interval + self.ping_interval_grace_period) * 1000, | ||
| 'maxPayload': self.max_http_buffer_size, | ||
| }) | ||
| s.send(pkt) | ||
@@ -446,3 +454,12 @@ s.schedule_ping() | ||
| try: | ||
| return self.handlers[event](*args) | ||
| try: | ||
| return self.handlers[event](*args) | ||
| except TypeError: | ||
| if event == 'disconnect' and \ | ||
| len(args) == 2: # pragma: no branch | ||
| # legacy disconnect events do not have a reason | ||
| # argument | ||
| return self.handlers[event](args[0]) | ||
| else: # pragma: no cover | ||
| raise | ||
| except: | ||
@@ -449,0 +466,0 @@ self.logger.exception(event + ' handler error') |
@@ -51,3 +51,4 @@ import sys | ||
| elif pkt.packet_type == packet.CLOSE: | ||
| self.close(wait=False, abort=True) | ||
| self.close(wait=False, abort=True, | ||
| reason=self.server.reason.CLIENT_DISCONNECT) | ||
| else: | ||
@@ -67,3 +68,4 @@ raise exceptions.UnknownPacketError() | ||
| # to their correct state of disconnected | ||
| self.close(wait=False, abort=False) | ||
| self.close(wait=False, abort=False, | ||
| reason=self.server.reason.PING_TIMEOUT) | ||
| return False | ||
@@ -102,3 +104,3 @@ return True | ||
| exc = sys.exc_info() | ||
| self.close(wait=False) | ||
| self.close(wait=False, reason=self.server.reason.TRANSPORT_ERROR) | ||
| raise exc[1].with_traceback(exc[2]) | ||
@@ -118,7 +120,10 @@ return packets | ||
| def close(self, wait=True, abort=False): | ||
| def close(self, wait=True, abort=False, reason=None): | ||
| """Close the socket connection.""" | ||
| if not self.closed and not self.closing: | ||
| self.closing = True | ||
| self.server._trigger_event('disconnect', self.sid, run_async=False) | ||
| self.server._trigger_event( | ||
| 'disconnect', self.sid, | ||
| reason or self.server.reason.SERVER_DISCONNECT, | ||
| run_async=False) | ||
| if not abort: | ||
@@ -144,3 +149,3 @@ self.send(packet.Packet(packet.CLOSE)) | ||
| if self.upgraded: | ||
| raise IOError('Socket has been upgraded already') | ||
| raise OSError('Socket has been upgraded already') | ||
| if self.server._async['websocket'] is None: | ||
@@ -147,0 +152,0 @@ # the selected async mode does not support websocket |
| Metadata-Version: 2.1 | ||
| Name: python-engineio | ||
| Version: 4.10.1 | ||
| Version: 4.11.0 | ||
| Summary: Engine.IO server and client for Python | ||
@@ -5,0 +5,0 @@ Author-email: Miguel Grinberg <miguel.grinberg@gmail.com> |
@@ -1,2 +0,1 @@ | ||
| import unittest | ||
| from unittest import mock | ||
@@ -7,3 +6,3 @@ | ||
| class AiohttpTests(unittest.TestCase): | ||
| class TestAiohttp: | ||
| def test_create_route(self): | ||
@@ -10,0 +9,0 @@ app = mock.MagicMock() |
+267
-276
@@ -1,4 +0,2 @@ | ||
| import asyncio | ||
| import os | ||
| import unittest | ||
| from unittest import mock | ||
@@ -9,20 +7,4 @@ | ||
| def AsyncMock(*args, **kwargs): | ||
| """Return a mock asynchronous function.""" | ||
| m = mock.MagicMock(*args, **kwargs) | ||
| async def mock_coro(*args, **kwargs): | ||
| return m(*args, **kwargs) | ||
| mock_coro.mock = m | ||
| return mock_coro | ||
| def _run(coro): | ||
| """Run the given coroutine.""" | ||
| return asyncio.get_event_loop().run_until_complete(coro) | ||
| class AsgiTests(unittest.TestCase): | ||
| def test_create_app(self): | ||
| class TestAsgi: | ||
| async def test_create_app(self): | ||
| app = async_asgi.ASGIApp( | ||
@@ -39,28 +21,28 @@ 'eio', | ||
| def test_engineio_routing(self): | ||
| async def test_engineio_routing(self): | ||
| mock_server = mock.MagicMock() | ||
| mock_server.handle_request = AsyncMock() | ||
| mock_server.handle_request = mock.AsyncMock() | ||
| app = async_asgi.ASGIApp(mock_server) | ||
| scope = {'type': 'http', 'path': '/engine.io/'} | ||
| _run(app(scope, 'receive', 'send')) | ||
| mock_server.handle_request.mock.assert_called_once_with( | ||
| await app(scope, 'receive', 'send') | ||
| mock_server.handle_request.assert_awaited_once_with( | ||
| scope, 'receive', 'send' | ||
| ) | ||
| mock_server.handle_request.mock.reset_mock() | ||
| mock_server.handle_request.reset_mock() | ||
| scope = {'type': 'http', 'path': '/engine.io/'} | ||
| _run(app(scope, 'receive', 'send')) | ||
| mock_server.handle_request.mock.assert_called_once_with( | ||
| await app(scope, 'receive', 'send') | ||
| mock_server.handle_request.assert_awaited_once_with( | ||
| scope, 'receive', 'send' | ||
| ) | ||
| mock_server.handle_request.mock.reset_mock() | ||
| mock_server.handle_request.reset_mock() | ||
| scope = {'type': 'http', 'path': '/engine.iofoo/'} | ||
| _run(app(scope, 'receive', AsyncMock())) | ||
| mock_server.handle_request.mock.assert_not_called() | ||
| await app(scope, 'receive', mock.AsyncMock()) | ||
| mock_server.handle_request.assert_not_awaited() | ||
| app = async_asgi.ASGIApp(mock_server, engineio_path=None) | ||
| mock_server.handle_request.mock.reset_mock() | ||
| mock_server.handle_request.reset_mock() | ||
| scope = {'type': 'http', 'path': '/foo'} | ||
| _run(app(scope, 'receive', 'send')) | ||
| mock_server.handle_request.mock.assert_called_once_with( | ||
| await app(scope, 'receive', 'send') | ||
| mock_server.handle_request.assert_awaited_once_with( | ||
| scope, 'receive', 'send' | ||
@@ -70,40 +52,40 @@ ) | ||
| app = async_asgi.ASGIApp(mock_server, engineio_path='mysocket.io') | ||
| mock_server.handle_request.mock.reset_mock() | ||
| mock_server.handle_request.reset_mock() | ||
| scope = {'type': 'http', 'path': '/mysocket.io'} | ||
| _run(app(scope, 'receive', 'send')) | ||
| mock_server.handle_request.mock.assert_called_once_with( | ||
| await app(scope, 'receive', 'send') | ||
| mock_server.handle_request.assert_awaited_once_with( | ||
| scope, 'receive', 'send' | ||
| ) | ||
| mock_server.handle_request.mock.reset_mock() | ||
| mock_server.handle_request.reset_mock() | ||
| scope = {'type': 'http', 'path': '/mysocket.io/'} | ||
| _run(app(scope, 'receive', 'send')) | ||
| mock_server.handle_request.mock.assert_called_once_with( | ||
| await app(scope, 'receive', 'send') | ||
| mock_server.handle_request.assert_awaited_once_with( | ||
| scope, 'receive', 'send' | ||
| ) | ||
| mock_server.handle_request.mock.reset_mock() | ||
| mock_server.handle_request.reset_mock() | ||
| scope = {'type': 'http', 'path': '/mysocket.io/foo'} | ||
| _run(app(scope, 'receive', 'send')) | ||
| mock_server.handle_request.mock.assert_called_once_with( | ||
| await app(scope, 'receive', 'send') | ||
| mock_server.handle_request.assert_awaited_once_with( | ||
| scope, 'receive', 'send' | ||
| ) | ||
| mock_server.handle_request.mock.reset_mock() | ||
| mock_server.handle_request.reset_mock() | ||
| scope = {'type': 'http', 'path': '/mysocket.iofoo'} | ||
| _run(app(scope, 'receive', AsyncMock())) | ||
| mock_server.handle_request.mock.assert_not_called() | ||
| await app(scope, 'receive', mock.AsyncMock()) | ||
| mock_server.handle_request.assert_not_awaited() | ||
| def test_other_app_routing(self): | ||
| other_app = AsyncMock() | ||
| async def test_other_app_routing(self): | ||
| other_app = mock.AsyncMock() | ||
| app = async_asgi.ASGIApp('eio', other_app) | ||
| scope = {'type': 'http', 'path': '/foo'} | ||
| _run(app(scope, 'receive', 'send')) | ||
| other_app.mock.assert_called_once_with(scope, 'receive', 'send') | ||
| await app(scope, 'receive', 'send') | ||
| other_app.assert_awaited_once_with(scope, 'receive', 'send') | ||
| def test_other_app_lifespan_routing(self): | ||
| other_app = AsyncMock() | ||
| async def test_other_app_lifespan_routing(self): | ||
| other_app = mock.AsyncMock() | ||
| app = async_asgi.ASGIApp('eio', other_app) | ||
| scope = {'type': 'lifespan'} | ||
| _run(app(scope, 'receive', 'send')) | ||
| other_app.mock.assert_called_once_with(scope, 'receive', 'send') | ||
| await app(scope, 'receive', 'send') | ||
| other_app.assert_awaited_once_with(scope, 'receive', 'send') | ||
| def test_static_file_routing(self): | ||
| async def test_static_file_routing(self): | ||
| root_dir = os.path.dirname(__file__) | ||
@@ -125,8 +107,8 @@ app = async_asgi.ASGIApp( | ||
| def check_path(path, status_code, content_type, body): | ||
| async def check_path(path, status_code, content_type, body): | ||
| scope = {'type': 'http', 'path': path} | ||
| receive = AsyncMock(return_value={'type': 'http.request'}) | ||
| send = AsyncMock() | ||
| _run(app(scope, receive, send)) | ||
| send.mock.assert_any_call( | ||
| receive = mock.AsyncMock(return_value={'type': 'http.request'}) | ||
| send = mock.AsyncMock() | ||
| await app(scope, receive, send) | ||
| send.assert_any_await( | ||
| { | ||
@@ -140,39 +122,40 @@ 'type': 'http.response.start', | ||
| ) | ||
| send.mock.assert_any_call( | ||
| send.assert_any_await( | ||
| {'type': 'http.response.body', 'body': body.encode('utf-8')} | ||
| ) | ||
| check_path('/', 200, 'text/html', '<html></html>\n') | ||
| check_path('/foo', 200, 'text/plain', '<html></html>\n') | ||
| check_path('/foo/bar', 404, 'text/plain', 'Not Found') | ||
| check_path('/static/index.html', 200, 'text/html', '<html></html>\n') | ||
| check_path('/static/foo.bar', 404, 'text/plain', 'Not Found') | ||
| check_path( | ||
| await check_path('/', 200, 'text/html', '<html></html>\n') | ||
| await check_path('/foo', 200, 'text/plain', '<html></html>\n') | ||
| await check_path('/foo/bar', 404, 'text/plain', 'Not Found') | ||
| await check_path('/static/index.html', 200, 'text/html', | ||
| '<html></html>\n') | ||
| await check_path('/static/foo.bar', 404, 'text/plain', 'Not Found') | ||
| await check_path( | ||
| '/static/test/index.html', 200, 'text/html', '<html></html>\n' | ||
| ) | ||
| check_path('/static/test/index.html', 200, 'text/html', | ||
| '<html></html>\n') | ||
| check_path('/static/test/files/', 200, 'text/html', | ||
| '<html>file</html>\n') | ||
| check_path('/static/test/files/file.txt', 200, 'text/plain', | ||
| 'file\n') | ||
| check_path('/static/test/files/x.html', 404, 'text/plain', | ||
| 'Not Found') | ||
| check_path('/static2/test/', 200, 'image/gif', '<html></html>\n') | ||
| check_path('/static2/test/index.html', 200, 'image/gif', | ||
| '<html></html>\n') | ||
| check_path('/static2/test/files/', 200, 'image/gif', | ||
| '<html>file</html>\n') | ||
| check_path('/static2/test/files/file.txt', 200, 'image/gif', | ||
| 'file\n') | ||
| check_path('/static2/test/files/x.html', 404, 'text/plain', | ||
| 'Not Found') | ||
| check_path('/bar/foo', 404, 'text/plain', 'Not Found') | ||
| check_path('', 404, 'text/plain', 'Not Found') | ||
| await check_path('/static/test/index.html', 200, 'text/html', | ||
| '<html></html>\n') | ||
| await check_path('/static/test/files/', 200, 'text/html', | ||
| '<html>file</html>\n') | ||
| await check_path('/static/test/files/file.txt', 200, 'text/plain', | ||
| 'file\n') | ||
| await check_path('/static/test/files/x.html', 404, 'text/plain', | ||
| 'Not Found') | ||
| await check_path('/static2/test/', 200, 'image/gif', '<html></html>\n') | ||
| await check_path('/static2/test/index.html', 200, 'image/gif', | ||
| '<html></html>\n') | ||
| await check_path('/static2/test/files/', 200, 'image/gif', | ||
| '<html>file</html>\n') | ||
| await check_path('/static2/test/files/file.txt', 200, 'image/gif', | ||
| 'file\n') | ||
| await check_path('/static2/test/files/x.html', 404, 'text/plain', | ||
| 'Not Found') | ||
| await check_path('/bar/foo', 404, 'text/plain', 'Not Found') | ||
| await check_path('', 404, 'text/plain', 'Not Found') | ||
| app.static_files[''] = 'index.html' | ||
| check_path('/static/test/', 200, 'text/html', '<html></html>\n') | ||
| await check_path('/static/test/', 200, 'text/html', '<html></html>\n') | ||
| app.static_files[''] = {'filename': 'index.html'} | ||
| check_path('/static/test/', 200, 'text/html', '<html></html>\n') | ||
| await check_path('/static/test/', 200, 'text/html', '<html></html>\n') | ||
@@ -183,22 +166,23 @@ app.static_files[''] = { | ||
| } | ||
| check_path('/static/test/', 200, 'image/gif', '<html></html>\n') | ||
| await check_path('/static/test/', 200, 'image/gif', '<html></html>\n') | ||
| app.static_files[''] = {'filename': 'test.gif'} | ||
| check_path('/static/test/', 404, 'text/plain', 'Not Found') | ||
| await check_path('/static/test/', 404, 'text/plain', 'Not Found') | ||
| app.static_files = {} | ||
| check_path('/static/test/index.html', 404, 'text/plain', 'Not Found') | ||
| await check_path('/static/test/index.html', 404, 'text/plain', | ||
| 'Not Found') | ||
| def test_lifespan_startup(self): | ||
| async def test_lifespan_startup(self): | ||
| app = async_asgi.ASGIApp('eio') | ||
| scope = {'type': 'lifespan'} | ||
| receive = AsyncMock(side_effect=[{'type': 'lifespan.startup'}, | ||
| {'type': 'lifespan.shutdown'}]) | ||
| send = AsyncMock() | ||
| _run(app(scope, receive, send)) | ||
| send.mock.assert_any_call( | ||
| receive = mock.AsyncMock(side_effect=[{'type': 'lifespan.startup'}, | ||
| {'type': 'lifespan.shutdown'}]) | ||
| send = mock.AsyncMock() | ||
| await app(scope, receive, send) | ||
| send.assert_any_await( | ||
| {'type': 'lifespan.startup.complete'} | ||
| ) | ||
| def test_lifespan_startup_sync_function(self): | ||
| async def test_lifespan_startup_sync_function(self): | ||
| up = False | ||
@@ -212,7 +196,7 @@ | ||
| scope = {'type': 'lifespan'} | ||
| receive = AsyncMock(side_effect=[{'type': 'lifespan.startup'}, | ||
| {'type': 'lifespan.shutdown'}]) | ||
| send = AsyncMock() | ||
| _run(app(scope, receive, send)) | ||
| send.mock.assert_any_call( | ||
| receive = mock.AsyncMock(side_effect=[{'type': 'lifespan.startup'}, | ||
| {'type': 'lifespan.shutdown'}]) | ||
| send = mock.AsyncMock() | ||
| await app(scope, receive, send) | ||
| send.assert_any_await( | ||
| {'type': 'lifespan.startup.complete'} | ||
@@ -222,3 +206,3 @@ ) | ||
| def test_lifespan_startup_async_function(self): | ||
| async def test_lifespan_startup_async_function(self): | ||
| up = False | ||
@@ -232,7 +216,7 @@ | ||
| scope = {'type': 'lifespan'} | ||
| receive = AsyncMock(side_effect=[{'type': 'lifespan.startup'}, | ||
| {'type': 'lifespan.shutdown'}]) | ||
| send = AsyncMock() | ||
| _run(app(scope, receive, send)) | ||
| send.mock.assert_any_call( | ||
| receive = mock.AsyncMock(side_effect=[{'type': 'lifespan.startup'}, | ||
| {'type': 'lifespan.shutdown'}]) | ||
| send = mock.AsyncMock() | ||
| await app(scope, receive, send) | ||
| send.assert_any_await( | ||
| {'type': 'lifespan.startup.complete'} | ||
@@ -242,3 +226,3 @@ ) | ||
| def test_lifespan_startup_function_exception(self): | ||
| async def test_lifespan_startup_function_exception(self): | ||
| up = False | ||
@@ -251,19 +235,19 @@ | ||
| scope = {'type': 'lifespan'} | ||
| receive = AsyncMock(side_effect=[{'type': 'lifespan.startup'}]) | ||
| send = AsyncMock() | ||
| _run(app(scope, receive, send)) | ||
| send.mock.assert_called_once_with({'type': 'lifespan.startup.failed'}) | ||
| receive = mock.AsyncMock(side_effect=[{'type': 'lifespan.startup'}]) | ||
| send = mock.AsyncMock() | ||
| await app(scope, receive, send) | ||
| send.assert_awaited_once_with({'type': 'lifespan.startup.failed'}) | ||
| assert not up | ||
| def test_lifespan_shutdown(self): | ||
| async def test_lifespan_shutdown(self): | ||
| app = async_asgi.ASGIApp('eio') | ||
| scope = {'type': 'lifespan'} | ||
| receive = AsyncMock(return_value={'type': 'lifespan.shutdown'}) | ||
| send = AsyncMock() | ||
| _run(app(scope, receive, send)) | ||
| send.mock.assert_called_once_with( | ||
| receive = mock.AsyncMock(return_value={'type': 'lifespan.shutdown'}) | ||
| send = mock.AsyncMock() | ||
| await app(scope, receive, send) | ||
| send.assert_awaited_once_with( | ||
| {'type': 'lifespan.shutdown.complete'} | ||
| ) | ||
| def test_lifespan_shutdown_sync_function(self): | ||
| async def test_lifespan_shutdown_sync_function(self): | ||
| down = False | ||
@@ -277,6 +261,6 @@ | ||
| scope = {'type': 'lifespan'} | ||
| receive = AsyncMock(return_value={'type': 'lifespan.shutdown'}) | ||
| send = AsyncMock() | ||
| _run(app(scope, receive, send)) | ||
| send.mock.assert_called_once_with( | ||
| receive = mock.AsyncMock(return_value={'type': 'lifespan.shutdown'}) | ||
| send = mock.AsyncMock() | ||
| await app(scope, receive, send) | ||
| send.assert_awaited_once_with( | ||
| {'type': 'lifespan.shutdown.complete'} | ||
@@ -286,3 +270,3 @@ ) | ||
| def test_lifespan_shutdown_async_function(self): | ||
| async def test_lifespan_shutdown_async_function(self): | ||
| down = False | ||
@@ -296,6 +280,6 @@ | ||
| scope = {'type': 'lifespan'} | ||
| receive = AsyncMock(return_value={'type': 'lifespan.shutdown'}) | ||
| send = AsyncMock() | ||
| _run(app(scope, receive, send)) | ||
| send.mock.assert_called_once_with( | ||
| receive = mock.AsyncMock(return_value={'type': 'lifespan.shutdown'}) | ||
| send = mock.AsyncMock() | ||
| await app(scope, receive, send) | ||
| send.assert_awaited_once_with( | ||
| {'type': 'lifespan.shutdown.complete'} | ||
@@ -305,3 +289,3 @@ ) | ||
| def test_lifespan_shutdown_function_exception(self): | ||
| async def test_lifespan_shutdown_function_exception(self): | ||
| down = False | ||
@@ -314,26 +298,26 @@ | ||
| scope = {'type': 'lifespan'} | ||
| receive = AsyncMock(return_value={'type': 'lifespan.shutdown'}) | ||
| send = AsyncMock() | ||
| _run(app(scope, receive, send)) | ||
| send.mock.assert_called_once_with({'type': 'lifespan.shutdown.failed'}) | ||
| receive = mock.AsyncMock(return_value={'type': 'lifespan.shutdown'}) | ||
| send = mock.AsyncMock() | ||
| await app(scope, receive, send) | ||
| send.assert_awaited_once_with({'type': 'lifespan.shutdown.failed'}) | ||
| assert not down | ||
| def test_lifespan_invalid(self): | ||
| async def test_lifespan_invalid(self): | ||
| app = async_asgi.ASGIApp('eio') | ||
| scope = {'type': 'lifespan'} | ||
| receive = AsyncMock(side_effect=[{'type': 'lifespan.foo'}, | ||
| {'type': 'lifespan.shutdown'}]) | ||
| send = AsyncMock() | ||
| _run(app(scope, receive, send)) | ||
| send.mock.assert_called_once_with( | ||
| receive = mock.AsyncMock(side_effect=[{'type': 'lifespan.foo'}, | ||
| {'type': 'lifespan.shutdown'}]) | ||
| send = mock.AsyncMock() | ||
| await app(scope, receive, send) | ||
| send.assert_awaited_once_with( | ||
| {'type': 'lifespan.shutdown.complete'} | ||
| ) | ||
| def test_not_found(self): | ||
| async def test_not_found(self): | ||
| app = async_asgi.ASGIApp('eio') | ||
| scope = {'type': 'http', 'path': '/foo'} | ||
| receive = AsyncMock(return_value={'type': 'http.request'}) | ||
| send = AsyncMock() | ||
| _run(app(scope, receive, send)) | ||
| send.mock.assert_any_call( | ||
| receive = mock.AsyncMock(return_value={'type': 'http.request'}) | ||
| send = mock.AsyncMock() | ||
| await app(scope, receive, send) | ||
| send.assert_any_await( | ||
| { | ||
@@ -345,29 +329,27 @@ 'type': 'http.response.start', | ||
| ) | ||
| send.mock.assert_any_call( | ||
| send.assert_any_await( | ||
| {'type': 'http.response.body', 'body': b'Not Found'} | ||
| ) | ||
| def test_translate_request(self): | ||
| receive = AsyncMock( | ||
| async def test_translate_request(self): | ||
| receive = mock.AsyncMock( | ||
| return_value={'type': 'http.request', 'body': b'hello world'} | ||
| ) | ||
| send = AsyncMock() | ||
| environ = _run( | ||
| async_asgi.translate_request( | ||
| { | ||
| 'type': 'http', | ||
| 'method': 'PUT', | ||
| 'headers': [ | ||
| (b'a', b'b'), | ||
| (b'c-c', b'd'), | ||
| (b'c_c', b'e'), | ||
| (b'content-type', b'application/json'), | ||
| (b'content-length', b'123'), | ||
| ], | ||
| 'path': '/foo/bar', | ||
| 'query_string': b'baz=1', | ||
| }, | ||
| receive, | ||
| send, | ||
| ) | ||
| send = mock.AsyncMock() | ||
| environ = await async_asgi.translate_request( | ||
| { | ||
| 'type': 'http', | ||
| 'method': 'PUT', | ||
| 'headers': [ | ||
| (b'a', b'b'), | ||
| (b'c-c', b'd'), | ||
| (b'c_c', b'e'), | ||
| (b'content-type', b'application/json'), | ||
| (b'content-length', b'123'), | ||
| ], | ||
| 'path': '/foo/bar', | ||
| 'query_string': b'baz=1', | ||
| }, | ||
| receive, | ||
| send, | ||
| ) | ||
@@ -390,27 +372,25 @@ expected_environ = { | ||
| assert environ['HTTP_C_C'] == 'd,e' or environ['HTTP_C_C'] == 'e,d' | ||
| body = _run(environ['wsgi.input'].read()) | ||
| body = await environ['wsgi.input'].read() | ||
| assert body == b'hello world' | ||
| def test_translate_request_no_query_string(self): | ||
| receive = AsyncMock( | ||
| async def test_translate_request_no_query_string(self): | ||
| receive = mock.AsyncMock( | ||
| return_value={'type': 'http.request', 'body': b'hello world'} | ||
| ) | ||
| send = AsyncMock() | ||
| environ = _run( | ||
| async_asgi.translate_request( | ||
| { | ||
| 'type': 'http', | ||
| 'method': 'PUT', | ||
| 'headers': [ | ||
| (b'a', b'b'), | ||
| (b'c-c', b'd'), | ||
| (b'c_c', b'e'), | ||
| (b'content-type', b'application/json'), | ||
| (b'content-length', b'123'), | ||
| ], | ||
| 'path': '/foo/bar', | ||
| }, | ||
| receive, | ||
| send, | ||
| ) | ||
| send = mock.AsyncMock() | ||
| environ = await async_asgi.translate_request( | ||
| { | ||
| 'type': 'http', | ||
| 'method': 'PUT', | ||
| 'headers': [ | ||
| (b'a', b'b'), | ||
| (b'c-c', b'd'), | ||
| (b'c_c', b'e'), | ||
| (b'content-type', b'application/json'), | ||
| (b'content-length', b'123'), | ||
| ], | ||
| 'path': '/foo/bar', | ||
| }, | ||
| receive, | ||
| send, | ||
| ) | ||
@@ -433,7 +413,7 @@ expected_environ = { | ||
| assert environ['HTTP_C_C'] == 'd,e' or environ['HTTP_C_C'] == 'e,d' | ||
| body = _run(environ['wsgi.input'].read()) | ||
| body = await environ['wsgi.input'].read() | ||
| assert body == b'hello world' | ||
| def test_translate_request_with_large_body(self): | ||
| receive = AsyncMock( | ||
| async def test_translate_request_with_large_body(self): | ||
| receive = mock.AsyncMock( | ||
| side_effect=[ | ||
@@ -446,21 +426,19 @@ {'type': 'http.request', 'body': b'hello ', 'more_body': True}, | ||
| ) | ||
| send = AsyncMock() | ||
| environ = _run( | ||
| async_asgi.translate_request( | ||
| { | ||
| 'type': 'http', | ||
| 'method': 'PUT', | ||
| 'headers': [ | ||
| (b'a', b'b'), | ||
| (b'c-c', b'd'), | ||
| (b'c_c', b'e'), | ||
| (b'content-type', b'application/json'), | ||
| (b'content-length', b'123'), | ||
| ], | ||
| 'path': '/foo/bar', | ||
| 'query_string': b'baz=1', | ||
| }, | ||
| receive, | ||
| send, | ||
| ) | ||
| send = mock.AsyncMock() | ||
| environ = await async_asgi.translate_request( | ||
| { | ||
| 'type': 'http', | ||
| 'method': 'PUT', | ||
| 'headers': [ | ||
| (b'a', b'b'), | ||
| (b'c-c', b'd'), | ||
| (b'c_c', b'e'), | ||
| (b'content-type', b'application/json'), | ||
| (b'content-length', b'123'), | ||
| ], | ||
| 'path': '/foo/bar', | ||
| 'query_string': b'baz=1', | ||
| }, | ||
| receive, | ||
| send, | ||
| ) | ||
@@ -483,48 +461,67 @@ expected_environ = { | ||
| assert environ['HTTP_C_C'] == 'd,e' or environ['HTTP_C_C'] == 'e,d' | ||
| body = _run(environ['wsgi.input'].read()) | ||
| body = await environ['wsgi.input'].read() | ||
| assert body == b'hello world' | ||
| def test_translate_websocket_request(self): | ||
| receive = AsyncMock(return_value={'type': 'websocket.connect'}) | ||
| send = AsyncMock() | ||
| _run( | ||
| async_asgi.translate_request( | ||
| { | ||
| 'type': 'websocket', | ||
| 'headers': [ | ||
| (b'a', b'b'), | ||
| (b'c-c', b'd'), | ||
| (b'c_c', b'e'), | ||
| (b'content-type', b'application/json'), | ||
| (b'content-length', b'123'), | ||
| ], | ||
| 'path': '/foo/bar', | ||
| 'query_string': b'baz=1', | ||
| }, | ||
| receive, | ||
| send, | ||
| ) | ||
| async def test_translate_websocket_request(self): | ||
| receive = mock.AsyncMock(return_value={'type': 'websocket.connect'}) | ||
| send = mock.AsyncMock() | ||
| await async_asgi.translate_request( | ||
| { | ||
| 'type': 'websocket', | ||
| 'headers': [ | ||
| (b'a', b'b'), | ||
| (b'c-c', b'd'), | ||
| (b'c_c', b'e'), | ||
| (b'content-type', b'application/json'), | ||
| (b'content-length', b'123'), | ||
| ], | ||
| 'path': '/foo/bar', | ||
| 'query_string': b'baz=1', | ||
| }, | ||
| receive, | ||
| send, | ||
| ) | ||
| send.mock.assert_not_called() | ||
| send.assert_not_awaited() | ||
| def test_translate_unknown_request(self): | ||
| receive = AsyncMock(return_value={'type': 'http.foo'}) | ||
| send = AsyncMock() | ||
| environ = _run( | ||
| async_asgi.translate_request( | ||
| {'type': 'http', 'path': '/foo/bar', 'query_string': b'baz=1'}, | ||
| receive, | ||
| send, | ||
| ) | ||
| async def test_translate_unknown_request(self): | ||
| receive = mock.AsyncMock(return_value={'type': 'http.foo'}) | ||
| send = mock.AsyncMock() | ||
| environ = await async_asgi.translate_request( | ||
| {'type': 'http', 'path': '/foo/bar', 'query_string': b'baz=1'}, | ||
| receive, | ||
| send, | ||
| ) | ||
| assert environ == {} | ||
| def test_make_response(self): | ||
| environ = {'asgi.send': AsyncMock(), 'asgi.scope': {'type': 'http'}} | ||
| _run( | ||
| async_asgi.make_response( | ||
| '202 ACCEPTED', [('foo', 'bar')], b'payload', environ | ||
| ) | ||
| async def test_translate_request_bad_unicode(self): | ||
| receive = mock.AsyncMock(return_value={'type': 'http.request', | ||
| 'body': b'foo'}) | ||
| send = mock.AsyncMock() | ||
| environ = await async_asgi.translate_request( | ||
| { | ||
| 'type': 'http.request', | ||
| 'headers': [ | ||
| (b'a', b'b'), | ||
| (b'c', b'\xa0'), | ||
| (b'e', b'f'), | ||
| ], | ||
| 'path': '/foo/bar', | ||
| 'query_string': b'baz=1&bad=\xa0', | ||
| }, | ||
| receive, | ||
| send, | ||
| ) | ||
| environ['asgi.send'].mock.assert_any_call( | ||
| assert environ['HTTP_A'] == 'b' | ||
| assert environ['HTTP_E'] == 'f' | ||
| assert 'HTTP_C' not in environ | ||
| assert environ['QUERY_STRING'] == '' | ||
| assert environ['RAW_URI'] == '/foo/bar' | ||
| async def test_make_response(self): | ||
| environ = {'asgi.send': mock.AsyncMock(), | ||
| 'asgi.scope': {'type': 'http'}} | ||
| await async_asgi.make_response( | ||
| '202 ACCEPTED', [('foo', 'bar')], b'payload', environ | ||
| ) | ||
| environ['asgi.send'].assert_any_await( | ||
| { | ||
@@ -536,49 +533,43 @@ 'type': 'http.response.start', | ||
| ) | ||
| environ['asgi.send'].mock.assert_any_call( | ||
| environ['asgi.send'].assert_any_await( | ||
| {'type': 'http.response.body', 'body': b'payload'} | ||
| ) | ||
| def test_make_response_websocket_accept(self): | ||
| async def test_make_response_websocket_accept(self): | ||
| environ = { | ||
| 'asgi.send': AsyncMock(), | ||
| 'asgi.send': mock.AsyncMock(), | ||
| 'asgi.scope': {'type': 'websocket'}, | ||
| } | ||
| _run( | ||
| async_asgi.make_response( | ||
| '200 OK', [('foo', 'bar')], b'payload', environ | ||
| ) | ||
| await async_asgi.make_response( | ||
| '200 OK', [('foo', 'bar')], b'payload', environ | ||
| ) | ||
| environ['asgi.send'].mock.assert_called_with( | ||
| environ['asgi.send'].assert_awaited_with( | ||
| {'type': 'websocket.accept', 'headers': [(b'foo', b'bar')]} | ||
| ) | ||
| def test_make_response_websocket_reject(self): | ||
| async def test_make_response_websocket_reject(self): | ||
| environ = { | ||
| 'asgi.send': AsyncMock(), | ||
| 'asgi.send': mock.AsyncMock(), | ||
| 'asgi.scope': {'type': 'websocket'}, | ||
| } | ||
| _run( | ||
| async_asgi.make_response( | ||
| '401 UNAUTHORIZED', [('foo', 'bar')], b'payload', environ | ||
| ) | ||
| await async_asgi.make_response( | ||
| '401 UNAUTHORIZED', [('foo', 'bar')], b'payload', environ | ||
| ) | ||
| environ['asgi.send'].mock.assert_called_with( | ||
| environ['asgi.send'].assert_awaited_with( | ||
| {'type': 'websocket.close', 'reason': 'payload'} | ||
| ) | ||
| def test_make_response_websocket_reject_no_payload(self): | ||
| async def test_make_response_websocket_reject_no_payload(self): | ||
| environ = { | ||
| 'asgi.send': AsyncMock(), | ||
| 'asgi.send': mock.AsyncMock(), | ||
| 'asgi.scope': {'type': 'websocket'}, | ||
| } | ||
| _run( | ||
| async_asgi.make_response( | ||
| '401 UNAUTHORIZED', [('foo', 'bar')], None, environ | ||
| ) | ||
| await async_asgi.make_response( | ||
| '401 UNAUTHORIZED', [('foo', 'bar')], None, environ | ||
| ) | ||
| environ['asgi.send'].mock.assert_called_with( | ||
| environ['asgi.send'].assert_awaited_with( | ||
| {'type': 'websocket.close'} | ||
| ) | ||
| def test_sub_app_routing(self): | ||
| async def test_sub_app_routing(self): | ||
@@ -597,13 +588,13 @@ class ASGIDispatcher: | ||
| other_app = AsyncMock() | ||
| other_app = mock.AsyncMock() | ||
| mock_server = mock.MagicMock() | ||
| mock_server.handle_request = AsyncMock() | ||
| mock_server.handle_request = mock.AsyncMock() | ||
| eio_app = async_asgi.ASGIApp(mock_server, engineio_path=None) | ||
| root_app = ASGIDispatcher({'/foo': other_app, '/eio': eio_app}) | ||
| scope = {'type': 'http', 'path': '/foo/bar'} | ||
| _run(root_app(scope, 'receive', 'send')) | ||
| other_app.mock.assert_called_once_with(scope, 'receive', 'send') | ||
| await root_app(scope, 'receive', 'send') | ||
| other_app.assert_awaited_once_with(scope, 'receive', 'send') | ||
| scope = {'type': 'http', 'path': '/eio/'} | ||
| _run(root_app(scope, 'receive', 'send')) | ||
| eio_app.engineio_server.handle_request.mock.assert_called_once_with( | ||
| await root_app(scope, 'receive', 'send') | ||
| eio_app.engineio_server.handle_request.assert_awaited_once_with( | ||
| scope, 'receive', 'send') |
+492
-500
| import asyncio | ||
| import ssl | ||
| import sys | ||
| import unittest | ||
| from unittest import mock | ||
@@ -20,46 +18,29 @@ | ||
| def AsyncMock(*args, **kwargs): | ||
| """Return a mock asynchronous function.""" | ||
| m = mock.MagicMock(*args, **kwargs) | ||
| async def mock_coro(*args, **kwargs): | ||
| return m(*args, **kwargs) | ||
| mock_coro.mock = m | ||
| return mock_coro | ||
| def _run(coro): | ||
| """Run the given coroutine.""" | ||
| return asyncio.get_event_loop().run_until_complete(coro) | ||
| @unittest.skipIf(sys.version_info < (3, 5), 'only for Python 3.5+') | ||
| class TestAsyncClient(unittest.TestCase): | ||
| def test_is_asyncio_based(self): | ||
| class TestAsyncClient: | ||
| async def test_is_asyncio_based(self): | ||
| c = async_client.AsyncClient() | ||
| assert c.is_asyncio_based() | ||
| def test_already_connected(self): | ||
| async def test_already_connected(self): | ||
| c = async_client.AsyncClient() | ||
| c.state = 'connected' | ||
| with pytest.raises(ValueError): | ||
| _run(c.connect('http://foo')) | ||
| await c.connect('http://foo') | ||
| def test_invalid_transports(self): | ||
| async def test_invalid_transports(self): | ||
| c = async_client.AsyncClient() | ||
| with pytest.raises(ValueError): | ||
| _run(c.connect('http://foo', transports=['foo', 'bar'])) | ||
| await c.connect('http://foo', transports=['foo', 'bar']) | ||
| def test_some_invalid_transports(self): | ||
| async def test_some_invalid_transports(self): | ||
| c = async_client.AsyncClient() | ||
| c._connect_websocket = AsyncMock() | ||
| _run(c.connect('http://foo', transports=['foo', 'websocket', 'bar'])) | ||
| c._connect_websocket = mock.AsyncMock() | ||
| await c.connect('http://foo', transports=['foo', 'websocket', 'bar']) | ||
| assert c.transports == ['websocket'] | ||
| def test_connect_polling(self): | ||
| async def test_connect_polling(self): | ||
| c = async_client.AsyncClient() | ||
| c._connect_polling = AsyncMock(return_value='foo') | ||
| assert _run(c.connect('http://foo')) == 'foo' | ||
| c._connect_polling.mock.assert_called_once_with( | ||
| c._connect_polling = mock.AsyncMock(return_value='foo') | ||
| assert await c.connect('http://foo') == 'foo' | ||
| c._connect_polling.assert_awaited_once_with( | ||
| 'http://foo', {}, 'engine.io' | ||
@@ -69,5 +50,5 @@ ) | ||
| c = async_client.AsyncClient() | ||
| c._connect_polling = AsyncMock(return_value='foo') | ||
| assert _run(c.connect('http://foo', transports=['polling'])) == 'foo' | ||
| c._connect_polling.mock.assert_called_once_with( | ||
| c._connect_polling = mock.AsyncMock(return_value='foo') | ||
| assert await c.connect('http://foo', transports=['polling']) == 'foo' | ||
| c._connect_polling.assert_awaited_once_with( | ||
| 'http://foo', {}, 'engine.io' | ||
@@ -77,16 +58,16 @@ ) | ||
| c = async_client.AsyncClient() | ||
| c._connect_polling = AsyncMock(return_value='foo') | ||
| c._connect_polling = mock.AsyncMock(return_value='foo') | ||
| assert ( | ||
| _run(c.connect('http://foo', transports=['polling', 'websocket'])) | ||
| await c.connect('http://foo', transports=['polling', 'websocket']) | ||
| == 'foo' | ||
| ) | ||
| c._connect_polling.mock.assert_called_once_with( | ||
| c._connect_polling.assert_awaited_once_with( | ||
| 'http://foo', {}, 'engine.io' | ||
| ) | ||
| def test_connect_websocket(self): | ||
| async def test_connect_websocket(self): | ||
| c = async_client.AsyncClient() | ||
| c._connect_websocket = AsyncMock(return_value='foo') | ||
| assert _run(c.connect('http://foo', transports=['websocket'])) == 'foo' | ||
| c._connect_websocket.mock.assert_called_once_with( | ||
| c._connect_websocket = mock.AsyncMock(return_value='foo') | ||
| assert await c.connect('http://foo', transports=['websocket']) == 'foo' | ||
| c._connect_websocket.assert_awaited_once_with( | ||
| 'http://foo', {}, 'engine.io' | ||
@@ -96,25 +77,25 @@ ) | ||
| c = async_client.AsyncClient() | ||
| c._connect_websocket = AsyncMock(return_value='foo') | ||
| assert _run(c.connect('http://foo', transports='websocket')) == 'foo' | ||
| c._connect_websocket.mock.assert_called_once_with( | ||
| c._connect_websocket = mock.AsyncMock(return_value='foo') | ||
| assert await c.connect('http://foo', transports='websocket') == 'foo' | ||
| c._connect_websocket.assert_awaited_once_with( | ||
| 'http://foo', {}, 'engine.io' | ||
| ) | ||
| def test_connect_query_string(self): | ||
| async def test_connect_query_string(self): | ||
| c = async_client.AsyncClient() | ||
| c._connect_polling = AsyncMock(return_value='foo') | ||
| assert _run(c.connect('http://foo?bar=baz')) == 'foo' | ||
| c._connect_polling.mock.assert_called_once_with( | ||
| c._connect_polling = mock.AsyncMock(return_value='foo') | ||
| assert await c.connect('http://foo?bar=baz') == 'foo' | ||
| c._connect_polling.assert_awaited_once_with( | ||
| 'http://foo?bar=baz', {}, 'engine.io' | ||
| ) | ||
| def test_connect_custom_headers(self): | ||
| async def test_connect_custom_headers(self): | ||
| c = async_client.AsyncClient() | ||
| c._connect_polling = AsyncMock(return_value='foo') | ||
| assert _run(c.connect('http://foo', headers={'Foo': 'Bar'})) == 'foo' | ||
| c._connect_polling.mock.assert_called_once_with( | ||
| c._connect_polling = mock.AsyncMock(return_value='foo') | ||
| assert await c.connect('http://foo', headers={'Foo': 'Bar'}) == 'foo' | ||
| c._connect_polling.assert_awaited_once_with( | ||
| 'http://foo', {'Foo': 'Bar'}, 'engine.io' | ||
| ) | ||
| def test_wait(self): | ||
| async def test_wait(self): | ||
| c = async_client.AsyncClient() | ||
@@ -127,11 +108,11 @@ done = [] | ||
| c.read_loop_task = fake_read_look_task() | ||
| _run(c.wait()) | ||
| await c.wait() | ||
| assert done == [True] | ||
| def test_wait_no_task(self): | ||
| async def test_wait_no_task(self): | ||
| c = async_client.AsyncClient() | ||
| c.read_loop_task = None | ||
| _run(c.wait()) | ||
| await c.wait() | ||
| def test_send(self): | ||
| async def test_send(self): | ||
| c = async_client.AsyncClient() | ||
@@ -144,5 +125,5 @@ saved_packets = [] | ||
| c._send_packet = fake_send_packet | ||
| _run(c.send('foo')) | ||
| _run(c.send('foo')) | ||
| _run(c.send(b'foo')) | ||
| await c.send('foo') | ||
| await c.send('foo') | ||
| await c.send(b'foo') | ||
| assert saved_packets[0].packet_type == packet.MESSAGE | ||
@@ -158,11 +139,11 @@ assert saved_packets[0].data == 'foo' | ||
| def test_disconnect_not_connected(self): | ||
| async def test_disconnect_not_connected(self): | ||
| c = async_client.AsyncClient() | ||
| c.state = 'foo' | ||
| c.sid = 'bar' | ||
| _run(c.disconnect()) | ||
| await c.disconnect() | ||
| assert c.state == 'disconnected' | ||
| assert c.sid is None | ||
| def test_disconnect_polling(self): | ||
| async def test_disconnect_polling(self): | ||
| c = async_client.AsyncClient() | ||
@@ -173,16 +154,16 @@ base_client.connected_clients.append(c) | ||
| c.queue = mock.MagicMock() | ||
| c.queue.put = AsyncMock() | ||
| c.queue.join = AsyncMock() | ||
| c.read_loop_task = AsyncMock()() | ||
| c.queue.put = mock.AsyncMock() | ||
| c.queue.join = mock.AsyncMock() | ||
| c.read_loop_task = mock.AsyncMock()() | ||
| c.ws = mock.MagicMock() | ||
| c.ws.close = AsyncMock() | ||
| c._trigger_event = AsyncMock() | ||
| _run(c.disconnect()) | ||
| c.ws.close.mock.assert_not_called() | ||
| c.ws.close = mock.AsyncMock() | ||
| c._trigger_event = mock.AsyncMock() | ||
| await c.disconnect() | ||
| c.ws.close.assert_not_awaited() | ||
| assert c not in base_client.connected_clients | ||
| c._trigger_event.mock.assert_called_once_with( | ||
| 'disconnect', run_async=False | ||
| c._trigger_event.assert_awaited_once_with( | ||
| 'disconnect', c.reason.CLIENT_DISCONNECT, run_async=False | ||
| ) | ||
| def test_disconnect_websocket(self): | ||
| async def test_disconnect_websocket(self): | ||
| c = async_client.AsyncClient() | ||
@@ -193,16 +174,16 @@ base_client.connected_clients.append(c) | ||
| c.queue = mock.MagicMock() | ||
| c.queue.put = AsyncMock() | ||
| c.queue.join = AsyncMock() | ||
| c.read_loop_task = AsyncMock()() | ||
| c.queue.put = mock.AsyncMock() | ||
| c.queue.join = mock.AsyncMock() | ||
| c.read_loop_task = mock.AsyncMock()() | ||
| c.ws = mock.MagicMock() | ||
| c.ws.close = AsyncMock() | ||
| c._trigger_event = AsyncMock() | ||
| _run(c.disconnect()) | ||
| c.ws.close.mock.assert_called_once_with() | ||
| c.ws.close = mock.AsyncMock() | ||
| c._trigger_event = mock.AsyncMock() | ||
| await c.disconnect() | ||
| c.ws.close.assert_awaited_once_with() | ||
| assert c not in base_client.connected_clients | ||
| c._trigger_event.mock.assert_called_once_with( | ||
| 'disconnect', run_async=False | ||
| c._trigger_event.assert_awaited_once_with( | ||
| 'disconnect', c.reason.CLIENT_DISCONNECT, run_async=False | ||
| ) | ||
| def test_disconnect_polling_abort(self): | ||
| async def test_disconnect_polling_abort(self): | ||
| c = async_client.AsyncClient() | ||
@@ -213,13 +194,13 @@ base_client.connected_clients.append(c) | ||
| c.queue = mock.MagicMock() | ||
| c.queue.put = AsyncMock() | ||
| c.queue.join = AsyncMock() | ||
| c.read_loop_task = AsyncMock()() | ||
| c.queue.put = mock.AsyncMock() | ||
| c.queue.join = mock.AsyncMock() | ||
| c.read_loop_task = mock.AsyncMock()() | ||
| c.ws = mock.MagicMock() | ||
| c.ws.close = AsyncMock() | ||
| _run(c.disconnect(abort=True)) | ||
| c.queue.join.mock.assert_not_called() | ||
| c.ws.close.mock.assert_not_called() | ||
| c.ws.close = mock.AsyncMock() | ||
| await c.disconnect(abort=True) | ||
| c.queue.join.assert_not_awaited() | ||
| c.ws.close.assert_not_awaited() | ||
| assert c not in base_client.connected_clients | ||
| def test_disconnect_websocket_abort(self): | ||
| async def test_disconnect_websocket_abort(self): | ||
| c = async_client.AsyncClient() | ||
@@ -230,13 +211,13 @@ base_client.connected_clients.append(c) | ||
| c.queue = mock.MagicMock() | ||
| c.queue.put = AsyncMock() | ||
| c.queue.join = AsyncMock() | ||
| c.read_loop_task = AsyncMock()() | ||
| c.queue.put = mock.AsyncMock() | ||
| c.queue.join = mock.AsyncMock() | ||
| c.read_loop_task = mock.AsyncMock()() | ||
| c.ws = mock.MagicMock() | ||
| c.ws.close = AsyncMock() | ||
| _run(c.disconnect(abort=True)) | ||
| c.queue.join.mock.assert_not_called() | ||
| c.ws.mock.assert_not_called() | ||
| c.ws.close = mock.AsyncMock() | ||
| await c.disconnect(abort=True) | ||
| c.queue.join.assert_not_awaited() | ||
| c.ws.assert_not_called() | ||
| assert c not in base_client.connected_clients | ||
| def test_background_tasks(self): | ||
| async def test_background_tasks(self): | ||
| r = [] | ||
@@ -248,13 +229,10 @@ | ||
| c = async_client.AsyncClient() | ||
| c.start_background_task(foo, 'bar') | ||
| pending = asyncio.all_tasks(loop=asyncio.get_event_loop()) \ | ||
| if hasattr(asyncio, 'all_tasks') else asyncio.Task.all_tasks() | ||
| asyncio.get_event_loop().run_until_complete(asyncio.wait(pending)) | ||
| await c.start_background_task(foo, 'bar') | ||
| assert r == ['bar'] | ||
| def test_sleep(self): | ||
| async def test_sleep(self): | ||
| c = async_client.AsyncClient() | ||
| _run(c.sleep(0)) | ||
| await c.sleep(0) | ||
| def test_create_queue(self): | ||
| async def test_create_queue(self): | ||
| c = async_client.AsyncClient() | ||
@@ -265,3 +243,3 @@ q = c.create_queue() | ||
| def test_create_event(self): | ||
| async def test_create_event(self): | ||
| c = async_client.AsyncClient() | ||
@@ -274,8 +252,8 @@ e = c.create_event() | ||
| @mock.patch('engineio.client.time.time', return_value=123.456) | ||
| def test_polling_connection_failed(self, _time): | ||
| async def test_polling_connection_failed(self, _time): | ||
| c = async_client.AsyncClient() | ||
| c._send_request = AsyncMock(return_value=None) | ||
| c._send_request = mock.AsyncMock(return_value=None) | ||
| with pytest.raises(exceptions.ConnectionError): | ||
| _run(c.connect('http://foo', headers={'Foo': 'Bar'})) | ||
| c._send_request.mock.assert_called_once_with( | ||
| await c.connect('http://foo', headers={'Foo': 'Bar'}) | ||
| c._send_request.assert_awaited_once_with( | ||
| 'GET', | ||
@@ -287,11 +265,11 @@ 'http://foo/engine.io/?transport=polling&EIO=4&t=123.456', | ||
| def test_polling_connection_404(self): | ||
| async def test_polling_connection_404(self): | ||
| c = async_client.AsyncClient() | ||
| c._send_request = AsyncMock() | ||
| c._send_request.mock.return_value.status = 404 | ||
| c._send_request.mock.return_value.json = AsyncMock( | ||
| c._send_request = mock.AsyncMock() | ||
| c._send_request.return_value.status = 404 | ||
| c._send_request.return_value.json = mock.AsyncMock( | ||
| return_value={'foo': 'bar'} | ||
| ) | ||
| try: | ||
| _run(c.connect('http://foo')) | ||
| await c.connect('http://foo') | ||
| except exceptions.ConnectionError as exc: | ||
@@ -304,11 +282,11 @@ assert len(exc.args) == 2 | ||
| def test_polling_connection_404_no_json(self): | ||
| async def test_polling_connection_404_no_json(self): | ||
| c = async_client.AsyncClient() | ||
| c._send_request = AsyncMock() | ||
| c._send_request.mock.return_value.status = 404 | ||
| c._send_request.mock.return_value.json = AsyncMock( | ||
| c._send_request = mock.AsyncMock() | ||
| c._send_request.return_value.status = 404 | ||
| c._send_request.return_value.json = mock.AsyncMock( | ||
| side_effect=aiohttp.ContentTypeError('foo', 'bar') | ||
| ) | ||
| try: | ||
| _run(c.connect('http://foo')) | ||
| await c.connect('http://foo') | ||
| except exceptions.ConnectionError as exc: | ||
@@ -321,15 +299,15 @@ assert len(exc.args) == 2 | ||
| def test_polling_connection_invalid_packet(self): | ||
| async def test_polling_connection_invalid_packet(self): | ||
| c = async_client.AsyncClient() | ||
| c._send_request = AsyncMock() | ||
| c._send_request.mock.return_value.status = 200 | ||
| c._send_request.mock.return_value.read = AsyncMock(return_value=b'foo') | ||
| c._send_request = mock.AsyncMock() | ||
| c._send_request.return_value.status = 200 | ||
| c._send_request.return_value.read = mock.AsyncMock(return_value=b'foo') | ||
| with pytest.raises(exceptions.ConnectionError): | ||
| _run(c.connect('http://foo')) | ||
| await c.connect('http://foo') | ||
| def test_polling_connection_no_open_packet(self): | ||
| async def test_polling_connection_no_open_packet(self): | ||
| c = async_client.AsyncClient() | ||
| c._send_request = AsyncMock() | ||
| c._send_request.mock.return_value.status = 200 | ||
| c._send_request.mock.return_value.read = AsyncMock( | ||
| c._send_request = mock.AsyncMock() | ||
| c._send_request.return_value.status = 200 | ||
| c._send_request.return_value.read = mock.AsyncMock( | ||
| return_value=payload.Payload( | ||
@@ -350,9 +328,9 @@ packets=[ | ||
| with pytest.raises(exceptions.ConnectionError): | ||
| _run(c.connect('http://foo')) | ||
| await c.connect('http://foo') | ||
| def test_polling_connection_successful(self): | ||
| async def test_polling_connection_successful(self): | ||
| c = async_client.AsyncClient() | ||
| c._send_request = AsyncMock() | ||
| c._send_request.mock.return_value.status = 200 | ||
| c._send_request.mock.return_value.read = AsyncMock( | ||
| c._send_request = mock.AsyncMock() | ||
| c._send_request.return_value.status = 200 | ||
| c._send_request.return_value.read = mock.AsyncMock( | ||
| return_value=payload.Payload( | ||
@@ -372,13 +350,13 @@ packets=[ | ||
| ) | ||
| c._read_loop_polling = AsyncMock() | ||
| c._read_loop_websocket = AsyncMock() | ||
| c._write_loop = AsyncMock() | ||
| on_connect = AsyncMock() | ||
| c._read_loop_polling = mock.AsyncMock() | ||
| c._read_loop_websocket = mock.AsyncMock() | ||
| c._write_loop = mock.AsyncMock() | ||
| on_connect = mock.AsyncMock() | ||
| c.on('connect', on_connect) | ||
| _run(c.connect('http://foo')) | ||
| await c.connect('http://foo') | ||
| c._read_loop_polling.mock.assert_called_once_with() | ||
| c._read_loop_websocket.mock.assert_not_called() | ||
| c._write_loop.mock.assert_called_once_with() | ||
| on_connect.mock.assert_called_once_with() | ||
| c._read_loop_polling.assert_called_once_with() | ||
| c._read_loop_websocket.assert_not_called() | ||
| c._write_loop.assert_called_once_with() | ||
| on_connect.assert_awaited_once_with() | ||
| assert c in base_client.connected_clients | ||
@@ -395,7 +373,7 @@ assert ( | ||
| def test_polling_https_noverify_connection_successful(self): | ||
| async def test_polling_https_noverify_connection_successful(self): | ||
| c = async_client.AsyncClient(ssl_verify=False) | ||
| c._send_request = AsyncMock() | ||
| c._send_request.mock.return_value.status = 200 | ||
| c._send_request.mock.return_value.read = AsyncMock( | ||
| c._send_request = mock.AsyncMock() | ||
| c._send_request.return_value.status = 200 | ||
| c._send_request.return_value.read = mock.AsyncMock( | ||
| return_value=payload.Payload( | ||
@@ -415,13 +393,13 @@ packets=[ | ||
| ) | ||
| c._read_loop_polling = AsyncMock() | ||
| c._read_loop_websocket = AsyncMock() | ||
| c._write_loop = AsyncMock() | ||
| on_connect = AsyncMock() | ||
| c._read_loop_polling = mock.AsyncMock() | ||
| c._read_loop_websocket = mock.AsyncMock() | ||
| c._write_loop = mock.AsyncMock() | ||
| on_connect = mock.AsyncMock() | ||
| c.on('connect', on_connect) | ||
| _run(c.connect('https://foo')) | ||
| await c.connect('https://foo') | ||
| c._read_loop_polling.mock.assert_called_once_with() | ||
| c._read_loop_websocket.mock.assert_not_called() | ||
| c._write_loop.mock.assert_called_once_with() | ||
| on_connect.mock.assert_called_once_with() | ||
| c._read_loop_polling.assert_called_once_with() | ||
| c._read_loop_websocket.assert_not_called() | ||
| c._write_loop.assert_called_once_with() | ||
| on_connect.assert_awaited_once_with() | ||
| assert c in base_client.connected_clients | ||
@@ -438,7 +416,7 @@ assert ( | ||
| def test_polling_connection_with_more_packets(self): | ||
| async def test_polling_connection_with_more_packets(self): | ||
| c = async_client.AsyncClient() | ||
| c._send_request = AsyncMock() | ||
| c._send_request.mock.return_value.status = 200 | ||
| c._send_request.mock.return_value.read = AsyncMock( | ||
| c._send_request = mock.AsyncMock() | ||
| c._send_request.return_value.status = 200 | ||
| c._send_request.return_value.read = mock.AsyncMock( | ||
| return_value=payload.Payload( | ||
@@ -459,20 +437,20 @@ packets=[ | ||
| ) | ||
| c._read_loop_polling = AsyncMock() | ||
| c._read_loop_websocket = AsyncMock() | ||
| c._write_loop = AsyncMock() | ||
| c._receive_packet = AsyncMock() | ||
| on_connect = AsyncMock() | ||
| c._read_loop_polling = mock.AsyncMock() | ||
| c._read_loop_websocket = mock.AsyncMock() | ||
| c._write_loop = mock.AsyncMock() | ||
| c._receive_packet = mock.AsyncMock() | ||
| on_connect = mock.AsyncMock() | ||
| c.on('connect', on_connect) | ||
| _run(c.connect('http://foo')) | ||
| assert c._receive_packet.mock.call_count == 1 | ||
| await c.connect('http://foo') | ||
| assert c._receive_packet.await_count == 1 | ||
| assert ( | ||
| c._receive_packet.mock.call_args_list[0][0][0].packet_type | ||
| c._receive_packet.await_args_list[0][0][0].packet_type | ||
| == packet.NOOP | ||
| ) | ||
| def test_polling_connection_upgraded(self): | ||
| async def test_polling_connection_upgraded(self): | ||
| c = async_client.AsyncClient() | ||
| c._send_request = AsyncMock() | ||
| c._send_request.mock.return_value.status = 200 | ||
| c._send_request.mock.return_value.read = AsyncMock( | ||
| c._send_request = mock.AsyncMock() | ||
| c._send_request.return_value.status = 200 | ||
| c._send_request.return_value.read = mock.AsyncMock( | ||
| return_value=payload.Payload( | ||
@@ -492,8 +470,8 @@ packets=[ | ||
| ) | ||
| c._connect_websocket = AsyncMock(return_value=True) | ||
| c._connect_websocket = mock.AsyncMock(return_value=True) | ||
| on_connect = mock.MagicMock() | ||
| c.on('connect', on_connect) | ||
| _run(c.connect('http://foo')) | ||
| await c.connect('http://foo') | ||
| c._connect_websocket.mock.assert_called_once_with( | ||
| c._connect_websocket.assert_awaited_once_with( | ||
| 'http://foo', {}, 'engine.io' | ||
@@ -512,7 +490,7 @@ ) | ||
| def test_polling_connection_not_upgraded(self): | ||
| async def test_polling_connection_not_upgraded(self): | ||
| c = async_client.AsyncClient() | ||
| c._send_request = AsyncMock() | ||
| c._send_request.mock.return_value.status = 200 | ||
| c._send_request.mock.return_value.read = AsyncMock( | ||
| c._send_request = mock.AsyncMock() | ||
| c._send_request.return_value.status = 200 | ||
| c._send_request.return_value.read = mock.AsyncMock( | ||
| return_value=payload.Payload( | ||
@@ -532,16 +510,16 @@ packets=[ | ||
| ) | ||
| c._connect_websocket = AsyncMock(return_value=False) | ||
| c._read_loop_polling = AsyncMock() | ||
| c._read_loop_websocket = AsyncMock() | ||
| c._write_loop = AsyncMock() | ||
| c._connect_websocket = mock.AsyncMock(return_value=False) | ||
| c._read_loop_polling = mock.AsyncMock() | ||
| c._read_loop_websocket = mock.AsyncMock() | ||
| c._write_loop = mock.AsyncMock() | ||
| on_connect = mock.MagicMock() | ||
| c.on('connect', on_connect) | ||
| _run(c.connect('http://foo')) | ||
| await c.connect('http://foo') | ||
| c._connect_websocket.mock.assert_called_once_with( | ||
| c._connect_websocket.assert_awaited_once_with( | ||
| 'http://foo', {}, 'engine.io' | ||
| ) | ||
| c._read_loop_polling.mock.assert_called_once_with() | ||
| c._read_loop_websocket.mock.assert_not_called() | ||
| c._write_loop.mock.assert_called_once_with() | ||
| c._read_loop_polling.assert_called_once_with() | ||
| c._read_loop_websocket.assert_not_called() | ||
| c._write_loop.assert_called_once_with() | ||
| on_connect.assert_called_once_with() | ||
@@ -551,17 +529,15 @@ assert c in base_client.connected_clients | ||
| @mock.patch('engineio.client.time.time', return_value=123.456) | ||
| def test_websocket_connection_failed(self, _time): | ||
| async def test_websocket_connection_failed(self, _time): | ||
| c = async_client.AsyncClient() | ||
| c.http = mock.MagicMock(closed=False) | ||
| c.http.ws_connect = AsyncMock( | ||
| c.http.ws_connect = mock.AsyncMock( | ||
| side_effect=[aiohttp.client_exceptions.ServerConnectionError()] | ||
| ) | ||
| with pytest.raises(exceptions.ConnectionError): | ||
| _run( | ||
| c.connect( | ||
| 'http://foo', | ||
| transports=['websocket'], | ||
| headers={'Foo': 'Bar'}, | ||
| ) | ||
| await c.connect( | ||
| 'http://foo', | ||
| transports=['websocket'], | ||
| headers={'Foo': 'Bar'}, | ||
| ) | ||
| c.http.ws_connect.mock.assert_called_once_with( | ||
| c.http.ws_connect.assert_awaited_once_with( | ||
| 'ws://foo/engine.io/?transport=websocket&EIO=4&t=123.456', | ||
@@ -573,3 +549,3 @@ headers={'Foo': 'Bar'}, | ||
| @mock.patch('engineio.client.time.time', return_value=123.456) | ||
| def test_websocket_connection_extra(self, _time): | ||
| async def test_websocket_connection_extra(self, _time): | ||
| c = async_client.AsyncClient(websocket_extra_options={ | ||
@@ -580,14 +556,12 @@ 'headers': {'Baz': 'Qux'}, | ||
| c.http = mock.MagicMock(closed=False) | ||
| c.http.ws_connect = AsyncMock( | ||
| c.http.ws_connect = mock.AsyncMock( | ||
| side_effect=[aiohttp.client_exceptions.ServerConnectionError()] | ||
| ) | ||
| with pytest.raises(exceptions.ConnectionError): | ||
| _run( | ||
| c.connect( | ||
| 'http://foo', | ||
| transports=['websocket'], | ||
| headers={'Foo': 'Bar'}, | ||
| ) | ||
| await c.connect( | ||
| 'http://foo', | ||
| transports=['websocket'], | ||
| headers={'Foo': 'Bar'}, | ||
| ) | ||
| c.http.ws_connect.mock.assert_called_once_with( | ||
| c.http.ws_connect.assert_awaited_once_with( | ||
| 'ws://foo/engine.io/?transport=websocket&EIO=4&t=123.456', | ||
@@ -599,11 +573,11 @@ headers={'Foo': 'Bar', 'Baz': 'Qux'}, | ||
| @mock.patch('engineio.client.time.time', return_value=123.456) | ||
| def test_websocket_upgrade_failed(self, _time): | ||
| async def test_websocket_upgrade_failed(self, _time): | ||
| c = async_client.AsyncClient() | ||
| c.http = mock.MagicMock(closed=False) | ||
| c.http.ws_connect = AsyncMock( | ||
| c.http.ws_connect = mock.AsyncMock( | ||
| side_effect=[aiohttp.client_exceptions.ServerConnectionError()] | ||
| ) | ||
| c.sid = '123' | ||
| assert not _run(c.connect('http://foo', transports=['websocket'])) | ||
| c.http.ws_connect.mock.assert_called_once_with( | ||
| assert not await c.connect('http://foo', transports=['websocket']) | ||
| c.http.ws_connect.assert_awaited_once_with( | ||
| 'ws://foo/engine.io/?transport=websocket&EIO=4&sid=123&t=123.456', | ||
@@ -614,22 +588,22 @@ headers={}, | ||
| def test_websocket_connection_no_open_packet(self): | ||
| async def test_websocket_connection_no_open_packet(self): | ||
| c = async_client.AsyncClient() | ||
| c.http = mock.MagicMock(closed=False) | ||
| c.http.ws_connect = AsyncMock() | ||
| ws = c.http.ws_connect.mock.return_value | ||
| ws.receive = AsyncMock() | ||
| ws.receive.mock.return_value.data = packet.Packet( | ||
| c.http.ws_connect = mock.AsyncMock() | ||
| ws = c.http.ws_connect.return_value | ||
| ws.receive = mock.AsyncMock() | ||
| ws.receive.return_value.data = packet.Packet( | ||
| packet.CLOSE | ||
| ).encode() | ||
| with pytest.raises(exceptions.ConnectionError): | ||
| _run(c.connect('http://foo', transports=['websocket'])) | ||
| await c.connect('http://foo', transports=['websocket']) | ||
| @mock.patch('engineio.client.time.time', return_value=123.456) | ||
| def test_websocket_connection_successful(self, _time): | ||
| async def test_websocket_connection_successful(self, _time): | ||
| c = async_client.AsyncClient() | ||
| c.http = mock.MagicMock(closed=False) | ||
| c.http.ws_connect = AsyncMock() | ||
| ws = c.http.ws_connect.mock.return_value | ||
| ws.receive = AsyncMock() | ||
| ws.receive.mock.return_value.data = packet.Packet( | ||
| c.http.ws_connect = mock.AsyncMock() | ||
| ws = c.http.ws_connect.return_value | ||
| ws.receive = mock.AsyncMock() | ||
| ws.receive.return_value.data = packet.Packet( | ||
| packet.OPEN, | ||
@@ -643,12 +617,12 @@ { | ||
| ).encode() | ||
| c._read_loop_polling = AsyncMock() | ||
| c._read_loop_websocket = AsyncMock() | ||
| c._write_loop = AsyncMock() | ||
| c._read_loop_polling = mock.AsyncMock() | ||
| c._read_loop_websocket = mock.AsyncMock() | ||
| c._write_loop = mock.AsyncMock() | ||
| on_connect = mock.MagicMock() | ||
| c.on('connect', on_connect) | ||
| _run(c.connect('ws://foo', transports=['websocket'])) | ||
| await c.connect('ws://foo', transports=['websocket']) | ||
| c._read_loop_polling.mock.assert_not_called() | ||
| c._read_loop_websocket.mock.assert_called_once_with() | ||
| c._write_loop.mock.assert_called_once_with() | ||
| c._read_loop_polling.assert_not_called() | ||
| c._read_loop_websocket.assert_called_once_with() | ||
| c._write_loop.assert_called_once_with() | ||
| on_connect.assert_called_once_with() | ||
@@ -663,3 +637,3 @@ assert c in base_client.connected_clients | ||
| assert c.ws == ws | ||
| c.http.ws_connect.mock.assert_called_once_with( | ||
| c.http.ws_connect.assert_awaited_once_with( | ||
| 'ws://foo/engine.io/?transport=websocket&EIO=4&t=123.456', | ||
@@ -671,9 +645,9 @@ headers={}, | ||
| @mock.patch('engineio.client.time.time', return_value=123.456) | ||
| def test_websocket_https_noverify_connection_successful(self, _time): | ||
| async def test_websocket_https_noverify_connection_successful(self, _time): | ||
| c = async_client.AsyncClient(ssl_verify=False) | ||
| c.http = mock.MagicMock(closed=False) | ||
| c.http.ws_connect = AsyncMock() | ||
| ws = c.http.ws_connect.mock.return_value | ||
| ws.receive = AsyncMock() | ||
| ws.receive.mock.return_value.data = packet.Packet( | ||
| c.http.ws_connect = mock.AsyncMock() | ||
| ws = c.http.ws_connect.return_value | ||
| ws.receive = mock.AsyncMock() | ||
| ws.receive.return_value.data = packet.Packet( | ||
| packet.OPEN, | ||
@@ -687,12 +661,12 @@ { | ||
| ).encode() | ||
| c._read_loop_polling = AsyncMock() | ||
| c._read_loop_websocket = AsyncMock() | ||
| c._write_loop = AsyncMock() | ||
| c._read_loop_polling = mock.AsyncMock() | ||
| c._read_loop_websocket = mock.AsyncMock() | ||
| c._write_loop = mock.AsyncMock() | ||
| on_connect = mock.MagicMock() | ||
| c.on('connect', on_connect) | ||
| _run(c.connect('wss://foo', transports=['websocket'])) | ||
| await c.connect('wss://foo', transports=['websocket']) | ||
| c._read_loop_polling.mock.assert_not_called() | ||
| c._read_loop_websocket.mock.assert_called_once_with() | ||
| c._write_loop.mock.assert_called_once_with() | ||
| c._read_loop_polling.assert_not_called() | ||
| c._read_loop_websocket.assert_called_once_with() | ||
| c._write_loop.assert_called_once_with() | ||
| on_connect.assert_called_once_with() | ||
@@ -707,3 +681,3 @@ assert c in base_client.connected_clients | ||
| assert c.ws == ws | ||
| _, kwargs = c.http.ws_connect.mock.call_args | ||
| _, kwargs = c.http.ws_connect.await_args | ||
| assert 'ssl' in kwargs | ||
@@ -714,9 +688,9 @@ assert isinstance(kwargs['ssl'], ssl.SSLContext) | ||
| @mock.patch('engineio.client.time.time', return_value=123.456) | ||
| def test_websocket_connection_with_cookies(self, _time): | ||
| async def test_websocket_connection_with_cookies(self, _time): | ||
| c = async_client.AsyncClient() | ||
| c.http = mock.MagicMock(closed=False) | ||
| c.http.ws_connect = AsyncMock() | ||
| ws = c.http.ws_connect.mock.return_value | ||
| ws.receive = AsyncMock() | ||
| ws.receive.mock.return_value.data = packet.Packet( | ||
| c.http.ws_connect = mock.AsyncMock() | ||
| ws = c.http.ws_connect.return_value | ||
| ws.receive = mock.AsyncMock() | ||
| ws.receive.return_value.data = packet.Packet( | ||
| packet.OPEN, | ||
@@ -735,9 +709,9 @@ { | ||
| c.http._cookie_jar[1].value = 'value2' | ||
| c._read_loop_polling = AsyncMock() | ||
| c._read_loop_websocket = AsyncMock() | ||
| c._write_loop = AsyncMock() | ||
| c._read_loop_polling = mock.AsyncMock() | ||
| c._read_loop_websocket = mock.AsyncMock() | ||
| c._write_loop = mock.AsyncMock() | ||
| on_connect = mock.MagicMock() | ||
| c.on('connect', on_connect) | ||
| _run(c.connect('ws://foo', transports=['websocket'])) | ||
| c.http.ws_connect.mock.assert_called_once_with( | ||
| await c.connect('ws://foo', transports=['websocket']) | ||
| c.http.ws_connect.assert_awaited_once_with( | ||
| 'ws://foo/engine.io/?transport=websocket&EIO=4&t=123.456', | ||
@@ -749,9 +723,9 @@ headers={}, | ||
| @mock.patch('engineio.client.time.time', return_value=123.456) | ||
| def test_websocket_connection_with_cookie_header(self, _time): | ||
| async def test_websocket_connection_with_cookie_header(self, _time): | ||
| c = async_client.AsyncClient() | ||
| c.http = mock.MagicMock(closed=False) | ||
| c.http.ws_connect = AsyncMock() | ||
| ws = c.http.ws_connect.mock.return_value | ||
| ws.receive = AsyncMock() | ||
| ws.receive.mock.return_value.data = packet.Packet( | ||
| c.http.ws_connect = mock.AsyncMock() | ||
| ws = c.http.ws_connect.return_value | ||
| ws.receive = mock.AsyncMock() | ||
| ws.receive.return_value.data = packet.Packet( | ||
| packet.OPEN, | ||
@@ -766,15 +740,13 @@ { | ||
| c.http._cookie_jar = [] | ||
| c._read_loop_polling = AsyncMock() | ||
| c._read_loop_websocket = AsyncMock() | ||
| c._write_loop = AsyncMock() | ||
| c._read_loop_polling = mock.AsyncMock() | ||
| c._read_loop_websocket = mock.AsyncMock() | ||
| c._write_loop = mock.AsyncMock() | ||
| on_connect = mock.MagicMock() | ||
| c.on('connect', on_connect) | ||
| _run( | ||
| c.connect( | ||
| 'ws://foo', | ||
| headers={'Cookie': 'key=value; key2=value2; key3="value3="'}, | ||
| transports=['websocket'], | ||
| ) | ||
| await c.connect( | ||
| 'ws://foo', | ||
| headers={'Cookie': 'key=value; key2=value2; key3="value3="'}, | ||
| transports=['websocket'], | ||
| ) | ||
| c.http.ws_connect.mock.assert_called_once_with( | ||
| c.http.ws_connect.assert_awaited_once_with( | ||
| 'ws://foo/engine.io/?transport=websocket&EIO=4&t=123.456', | ||
@@ -789,9 +761,9 @@ headers={}, | ||
| @mock.patch('engineio.client.time.time', return_value=123.456) | ||
| def test_websocket_connection_with_cookies_and_headers(self, _time): | ||
| async def test_websocket_connection_with_cookies_and_headers(self, _time): | ||
| c = async_client.AsyncClient() | ||
| c.http = mock.MagicMock(closed=False) | ||
| c.http.ws_connect = AsyncMock() | ||
| ws = c.http.ws_connect.mock.return_value | ||
| ws.receive = AsyncMock() | ||
| ws.receive.mock.return_value.data = packet.Packet( | ||
| c.http.ws_connect = mock.AsyncMock() | ||
| ws = c.http.ws_connect.return_value | ||
| ws.receive = mock.AsyncMock() | ||
| ws.receive.return_value.data = packet.Packet( | ||
| packet.OPEN, | ||
@@ -810,15 +782,13 @@ { | ||
| c.http._cookie_jar[1].value = 'value2' | ||
| c._read_loop_polling = AsyncMock() | ||
| c._read_loop_websocket = AsyncMock() | ||
| c._write_loop = AsyncMock() | ||
| c._read_loop_polling = mock.AsyncMock() | ||
| c._read_loop_websocket = mock.AsyncMock() | ||
| c._write_loop = mock.AsyncMock() | ||
| on_connect = mock.MagicMock() | ||
| c.on('connect', on_connect) | ||
| _run( | ||
| c.connect( | ||
| 'ws://foo', | ||
| headers={'Foo': 'Bar', 'Cookie': 'key3=value3'}, | ||
| transports=['websocket'], | ||
| ) | ||
| await c.connect( | ||
| 'ws://foo', | ||
| headers={'Foo': 'Bar', 'Cookie': 'key3=value3'}, | ||
| transports=['websocket'], | ||
| ) | ||
| c.http.ws_connect.mock.assert_called_once_with( | ||
| c.http.ws_connect.assert_awaited_once_with( | ||
| 'ws://foo/engine.io/?transport=websocket&EIO=4&t=123.456', | ||
@@ -832,9 +802,9 @@ headers={'Foo': 'Bar'}, | ||
| def test_websocket_upgrade_no_pong(self): | ||
| async def test_websocket_upgrade_no_pong(self): | ||
| c = async_client.AsyncClient() | ||
| c.http = mock.MagicMock(closed=False) | ||
| c.http.ws_connect = AsyncMock() | ||
| ws = c.http.ws_connect.mock.return_value | ||
| ws.receive = AsyncMock() | ||
| ws.receive.mock.return_value.data = packet.Packet( | ||
| c.http.ws_connect = mock.AsyncMock() | ||
| ws = c.http.ws_connect.return_value | ||
| ws.receive = mock.AsyncMock() | ||
| ws.receive.return_value.data = packet.Packet( | ||
| packet.OPEN, | ||
@@ -848,42 +818,42 @@ { | ||
| ).encode() | ||
| ws.send_str = AsyncMock() | ||
| ws.send_str = mock.AsyncMock() | ||
| c.sid = '123' | ||
| c.current_transport = 'polling' | ||
| c._read_loop_polling = AsyncMock() | ||
| c._read_loop_websocket = AsyncMock() | ||
| c._write_loop = AsyncMock() | ||
| c._read_loop_polling = mock.AsyncMock() | ||
| c._read_loop_websocket = mock.AsyncMock() | ||
| c._write_loop = mock.AsyncMock() | ||
| on_connect = mock.MagicMock() | ||
| c.on('connect', on_connect) | ||
| assert not _run(c.connect('ws://foo', transports=['websocket'])) | ||
| assert not await c.connect('ws://foo', transports=['websocket']) | ||
| c._read_loop_polling.mock.assert_not_called() | ||
| c._read_loop_websocket.mock.assert_not_called() | ||
| c._write_loop.mock.assert_not_called() | ||
| c._read_loop_polling.assert_not_called() | ||
| c._read_loop_websocket.assert_not_called() | ||
| c._write_loop.assert_not_called() | ||
| on_connect.assert_not_called() | ||
| assert c.transport() == 'polling' | ||
| ws.send_str.mock.assert_called_once_with('2probe') | ||
| ws.send_str.assert_awaited_once_with('2probe') | ||
| def test_websocket_upgrade_successful(self): | ||
| async def test_websocket_upgrade_successful(self): | ||
| c = async_client.AsyncClient() | ||
| c.http = mock.MagicMock(closed=False) | ||
| c.http.ws_connect = AsyncMock() | ||
| ws = c.http.ws_connect.mock.return_value | ||
| ws.receive = AsyncMock() | ||
| ws.receive.mock.return_value.data = packet.Packet( | ||
| c.http.ws_connect = mock.AsyncMock() | ||
| ws = c.http.ws_connect.return_value | ||
| ws.receive = mock.AsyncMock() | ||
| ws.receive.return_value.data = packet.Packet( | ||
| packet.PONG, 'probe' | ||
| ).encode() | ||
| ws.send_str = AsyncMock() | ||
| ws.send_str = mock.AsyncMock() | ||
| c.sid = '123' | ||
| c.base_url = 'http://foo' | ||
| c.current_transport = 'polling' | ||
| c._read_loop_polling = AsyncMock() | ||
| c._read_loop_websocket = AsyncMock() | ||
| c._write_loop = AsyncMock() | ||
| c._read_loop_polling = mock.AsyncMock() | ||
| c._read_loop_websocket = mock.AsyncMock() | ||
| c._write_loop = mock.AsyncMock() | ||
| on_connect = mock.MagicMock() | ||
| c.on('connect', on_connect) | ||
| assert _run(c.connect('ws://foo', transports=['websocket'])) | ||
| assert await c.connect('ws://foo', transports=['websocket']) | ||
| c._read_loop_polling.mock.assert_not_called() | ||
| c._read_loop_websocket.mock.assert_called_once_with() | ||
| c._write_loop.mock.assert_called_once_with() | ||
| c._read_loop_polling.assert_not_called() | ||
| c._read_loop_websocket.assert_called_once_with() | ||
| c._write_loop.assert_called_once_with() | ||
| on_connect.assert_not_called() # was called by polling | ||
@@ -895,52 +865,53 @@ assert c not in base_client.connected_clients # was added by polling | ||
| assert c.ws == ws | ||
| assert ws.send_str.mock.call_args_list[0] == (('2probe',),) # ping | ||
| assert ws.send_str.mock.call_args_list[1] == (('5',),) # upgrade | ||
| assert ws.send_str.await_args_list[0] == (('2probe',),) # ping | ||
| assert ws.send_str.await_args_list[1] == (('5',),) # upgrade | ||
| def test_receive_unknown_packet(self): | ||
| async def test_receive_unknown_packet(self): | ||
| c = async_client.AsyncClient() | ||
| _run(c._receive_packet(packet.Packet(encoded_packet='9'))) | ||
| await c._receive_packet(packet.Packet(encoded_packet='9')) | ||
| # should be ignored | ||
| def test_receive_noop_packet(self): | ||
| async def test_receive_noop_packet(self): | ||
| c = async_client.AsyncClient() | ||
| _run(c._receive_packet(packet.Packet(packet.NOOP))) | ||
| await c._receive_packet(packet.Packet(packet.NOOP)) | ||
| # should be ignored | ||
| def test_receive_ping_packet(self): | ||
| async def test_receive_ping_packet(self): | ||
| c = async_client.AsyncClient() | ||
| c._send_packet = AsyncMock() | ||
| _run(c._receive_packet(packet.Packet(packet.PING))) | ||
| assert c._send_packet.mock.call_args_list[0][0][0].encode() == '3' | ||
| c._send_packet = mock.AsyncMock() | ||
| await c._receive_packet(packet.Packet(packet.PING)) | ||
| assert c._send_packet.await_args_list[0][0][0].encode() == '3' | ||
| def test_receive_message_packet(self): | ||
| async def test_receive_message_packet(self): | ||
| c = async_client.AsyncClient() | ||
| c._trigger_event = AsyncMock() | ||
| _run(c._receive_packet(packet.Packet(packet.MESSAGE, {'foo': 'bar'}))) | ||
| c._trigger_event.mock.assert_called_once_with( | ||
| c._trigger_event = mock.AsyncMock() | ||
| await c._receive_packet(packet.Packet(packet.MESSAGE, {'foo': 'bar'})) | ||
| c._trigger_event.assert_awaited_once_with( | ||
| 'message', {'foo': 'bar'}, run_async=True | ||
| ) | ||
| def test_receive_close_packet(self): | ||
| async def test_receive_close_packet(self): | ||
| c = async_client.AsyncClient() | ||
| c.disconnect = AsyncMock() | ||
| _run(c._receive_packet(packet.Packet(packet.CLOSE))) | ||
| c.disconnect.mock.assert_called_once_with(abort=True) | ||
| c.disconnect = mock.AsyncMock() | ||
| await c._receive_packet(packet.Packet(packet.CLOSE)) | ||
| c.disconnect.assert_awaited_once_with( | ||
| abort=True, reason=c.reason.SERVER_DISCONNECT) | ||
| def test_send_packet_disconnected(self): | ||
| async def test_send_packet_disconnected(self): | ||
| c = async_client.AsyncClient() | ||
| c.queue = c.create_queue() | ||
| c.state = 'disconnected' | ||
| _run(c._send_packet(packet.Packet(packet.NOOP))) | ||
| await c._send_packet(packet.Packet(packet.NOOP)) | ||
| assert c.queue.empty() | ||
| def test_send_packet(self): | ||
| async def test_send_packet(self): | ||
| c = async_client.AsyncClient() | ||
| c.queue = c.create_queue() | ||
| c.state = 'connected' | ||
| _run(c._send_packet(packet.Packet(packet.NOOP))) | ||
| await c._send_packet(packet.Packet(packet.NOOP)) | ||
| assert not c.queue.empty() | ||
| pkt = _run(c.queue.get()) | ||
| pkt = await c.queue.get() | ||
| assert pkt.packet_type == packet.NOOP | ||
| def test_trigger_event_function(self): | ||
| async def test_trigger_event_function(self): | ||
| result = [] | ||
@@ -954,6 +925,6 @@ | ||
| c.on('message', handler=foo_handler) | ||
| _run(c._trigger_event('message', 'bar')) | ||
| await c._trigger_event('message', 'bar') | ||
| assert result == ['ok', 'bar'] | ||
| def test_trigger_event_coroutine(self): | ||
| async def test_trigger_event_coroutine(self): | ||
| result = [] | ||
@@ -967,6 +938,6 @@ | ||
| c.on('message', handler=foo_handler) | ||
| _run(c._trigger_event('message', 'bar')) | ||
| await c._trigger_event('message', 'bar') | ||
| assert result == ['ok', 'bar'] | ||
| def test_trigger_event_function_error(self): | ||
| async def test_trigger_event_function_error(self): | ||
| def connect_handler(arg): | ||
@@ -981,6 +952,6 @@ return 1 / 0 | ||
| c.on('message', handler=foo_handler) | ||
| assert not _run(c._trigger_event('connect', '123')) | ||
| assert _run(c._trigger_event('message', 'bar')) is None | ||
| assert not await c._trigger_event('connect', '123') | ||
| assert await c._trigger_event('message', 'bar') is None | ||
| def test_trigger_event_coroutine_error(self): | ||
| async def test_trigger_event_coroutine_error(self): | ||
| async def connect_handler(arg): | ||
@@ -995,6 +966,6 @@ return 1 / 0 | ||
| c.on('message', handler=foo_handler) | ||
| assert not _run(c._trigger_event('connect', '123')) | ||
| assert _run(c._trigger_event('message', 'bar')) is None | ||
| assert not await c._trigger_event('connect', '123') | ||
| assert await c._trigger_event('message', 'bar') is None | ||
| def test_trigger_event_function_async(self): | ||
| async def test_trigger_event_function_async(self): | ||
| result = [] | ||
@@ -1008,7 +979,7 @@ | ||
| c.on('message', handler=foo_handler) | ||
| fut = _run(c._trigger_event('message', 'bar', run_async=True)) | ||
| asyncio.get_event_loop().run_until_complete(fut) | ||
| fut = await c._trigger_event('message', 'bar', run_async=True) | ||
| await fut | ||
| assert result == ['ok', 'bar'] | ||
| def test_trigger_event_coroutine_async(self): | ||
| async def test_trigger_event_coroutine_async(self): | ||
| result = [] | ||
@@ -1022,7 +993,7 @@ | ||
| c.on('message', handler=foo_handler) | ||
| fut = _run(c._trigger_event('message', 'bar', run_async=True)) | ||
| asyncio.get_event_loop().run_until_complete(fut) | ||
| fut = await c._trigger_event('message', 'bar', run_async=True) | ||
| await fut | ||
| assert result == ['ok', 'bar'] | ||
| def test_trigger_event_function_async_error(self): | ||
| async def test_trigger_event_function_async_error(self): | ||
| result = [] | ||
@@ -1036,8 +1007,8 @@ | ||
| c.on('message', handler=foo_handler) | ||
| fut = _run(c._trigger_event('message', 'bar', run_async=True)) | ||
| fut = await c._trigger_event('message', 'bar', run_async=True) | ||
| with pytest.raises(ZeroDivisionError): | ||
| asyncio.get_event_loop().run_until_complete(fut) | ||
| await fut | ||
| assert result == ['bar'] | ||
| def test_trigger_event_coroutine_async_error(self): | ||
| async def test_trigger_event_coroutine_async_error(self): | ||
| result = [] | ||
@@ -1051,24 +1022,44 @@ | ||
| c.on('message', handler=foo_handler) | ||
| fut = _run(c._trigger_event('message', 'bar', run_async=True)) | ||
| fut = await c._trigger_event('message', 'bar', run_async=True) | ||
| with pytest.raises(ZeroDivisionError): | ||
| asyncio.get_event_loop().run_until_complete(fut) | ||
| await fut | ||
| assert result == ['bar'] | ||
| def test_trigger_unknown_event(self): | ||
| async def test_trigger_unknown_event(self): | ||
| c = async_client.AsyncClient() | ||
| _run(c._trigger_event('connect', run_async=False)) | ||
| _run(c._trigger_event('message', 123, run_async=True)) | ||
| await c._trigger_event('connect', run_async=False) | ||
| await c._trigger_event('message', 123, run_async=True) | ||
| # should do nothing | ||
| def test_read_loop_polling_disconnected(self): | ||
| async def test_trigger_legacy_disconnect_event(self): | ||
| c = async_client.AsyncClient() | ||
| @c.on('disconnect') | ||
| def baz(): | ||
| return 'baz' | ||
| r = await c._trigger_event('disconnect', 'foo') | ||
| assert r == 'baz' | ||
| async def test_trigger_legacy_disconnect_event_async(self): | ||
| c = async_client.AsyncClient() | ||
| @c.on('disconnect') | ||
| async def baz(): | ||
| return 'baz' | ||
| r = await c._trigger_event('disconnect', 'foo') | ||
| assert r == 'baz' | ||
| async def test_read_loop_polling_disconnected(self): | ||
| c = async_client.AsyncClient() | ||
| c.state = 'disconnected' | ||
| c._trigger_event = AsyncMock() | ||
| c.write_loop_task = AsyncMock()() | ||
| _run(c._read_loop_polling()) | ||
| c._trigger_event.mock.assert_not_called() | ||
| c._trigger_event = mock.AsyncMock() | ||
| c.write_loop_task = mock.AsyncMock()() | ||
| await c._read_loop_polling() | ||
| c._trigger_event.assert_not_awaited() | ||
| # should not block | ||
| @mock.patch('engineio.client.time.time', return_value=123.456) | ||
| def test_read_loop_polling_no_response(self, _time): | ||
| async def test_read_loop_polling_no_response(self, _time): | ||
| c = async_client.AsyncClient() | ||
@@ -1080,18 +1071,18 @@ c.ping_interval = 25 | ||
| c.queue = mock.MagicMock() | ||
| c.queue.put = AsyncMock() | ||
| c._send_request = AsyncMock(return_value=None) | ||
| c._trigger_event = AsyncMock() | ||
| c.write_loop_task = AsyncMock()() | ||
| _run(c._read_loop_polling()) | ||
| c.queue.put = mock.AsyncMock() | ||
| c._send_request = mock.AsyncMock(return_value=None) | ||
| c._trigger_event = mock.AsyncMock() | ||
| c.write_loop_task = mock.AsyncMock()() | ||
| await c._read_loop_polling() | ||
| assert c.state == 'disconnected' | ||
| c.queue.put.mock.assert_called_once_with(None) | ||
| c._send_request.mock.assert_called_once_with( | ||
| c.queue.put.assert_awaited_once_with(None) | ||
| c._send_request.assert_awaited_once_with( | ||
| 'GET', 'http://foo&t=123.456', timeout=30 | ||
| ) | ||
| c._trigger_event.mock.assert_called_once_with( | ||
| 'disconnect', run_async=False | ||
| c._trigger_event.assert_awaited_once_with( | ||
| 'disconnect', c.reason.TRANSPORT_ERROR, run_async=False | ||
| ) | ||
| @mock.patch('engineio.client.time.time', return_value=123.456) | ||
| def test_read_loop_polling_bad_status(self, _time): | ||
| async def test_read_loop_polling_bad_status(self, _time): | ||
| c = async_client.AsyncClient() | ||
@@ -1103,10 +1094,10 @@ c.ping_interval = 25 | ||
| c.queue = mock.MagicMock() | ||
| c.queue.put = AsyncMock() | ||
| c._send_request = AsyncMock() | ||
| c._send_request.mock.return_value.status = 400 | ||
| c.write_loop_task = AsyncMock()() | ||
| _run(c._read_loop_polling()) | ||
| c.queue.put = mock.AsyncMock() | ||
| c._send_request = mock.AsyncMock() | ||
| c._send_request.return_value.status = 400 | ||
| c.write_loop_task = mock.AsyncMock()() | ||
| await c._read_loop_polling() | ||
| assert c.state == 'disconnected' | ||
| c.queue.put.mock.assert_called_once_with(None) | ||
| c._send_request.mock.assert_called_once_with( | ||
| c.queue.put.assert_awaited_once_with(None) | ||
| c._send_request.assert_awaited_once_with( | ||
| 'GET', 'http://foo&t=123.456', timeout=30 | ||
@@ -1116,3 +1107,3 @@ ) | ||
| @mock.patch('engineio.client.time.time', return_value=123.456) | ||
| def test_read_loop_polling_bad_packet(self, _time): | ||
| async def test_read_loop_polling_bad_packet(self, _time): | ||
| c = async_client.AsyncClient() | ||
@@ -1124,15 +1115,15 @@ c.ping_interval = 25 | ||
| c.queue = mock.MagicMock() | ||
| c.queue.put = AsyncMock() | ||
| c._send_request = AsyncMock() | ||
| c._send_request.mock.return_value.status = 200 | ||
| c._send_request.mock.return_value.read = AsyncMock(return_value=b'foo') | ||
| c.write_loop_task = AsyncMock()() | ||
| _run(c._read_loop_polling()) | ||
| c.queue.put = mock.AsyncMock() | ||
| c._send_request = mock.AsyncMock() | ||
| c._send_request.return_value.status = 200 | ||
| c._send_request.return_value.read = mock.AsyncMock(return_value=b'foo') | ||
| c.write_loop_task = mock.AsyncMock()() | ||
| await c._read_loop_polling() | ||
| assert c.state == 'disconnected' | ||
| c.queue.put.mock.assert_called_once_with(None) | ||
| c._send_request.mock.assert_called_once_with( | ||
| c.queue.put.assert_awaited_once_with(None) | ||
| c._send_request.assert_awaited_once_with( | ||
| 'GET', 'http://foo&t=123.456', timeout=65 | ||
| ) | ||
| def test_read_loop_polling(self): | ||
| async def test_read_loop_polling(self): | ||
| c = async_client.AsyncClient() | ||
@@ -1144,8 +1135,8 @@ c.ping_interval = 25 | ||
| c.queue = mock.MagicMock() | ||
| c.queue.put = AsyncMock() | ||
| c._send_request = AsyncMock() | ||
| c._send_request.mock.side_effect = [ | ||
| c.queue.put = mock.AsyncMock() | ||
| c._send_request = mock.AsyncMock() | ||
| c._send_request.side_effect = [ | ||
| mock.MagicMock( | ||
| status=200, | ||
| read=AsyncMock( | ||
| read=mock.AsyncMock( | ||
| return_value=payload.Payload( | ||
@@ -1161,20 +1152,20 @@ packets=[ | ||
| ] | ||
| c.write_loop_task = AsyncMock()() | ||
| c._receive_packet = AsyncMock() | ||
| _run(c._read_loop_polling()) | ||
| c.write_loop_task = mock.AsyncMock()() | ||
| c._receive_packet = mock.AsyncMock() | ||
| await c._read_loop_polling() | ||
| assert c.state == 'disconnected' | ||
| c.queue.put.mock.assert_called_once_with(None) | ||
| assert c._send_request.mock.call_count == 2 | ||
| assert c._receive_packet.mock.call_count == 2 | ||
| assert c._receive_packet.mock.call_args_list[0][0][0].encode() == '2' | ||
| assert c._receive_packet.mock.call_args_list[1][0][0].encode() == '6' | ||
| c.queue.put.assert_awaited_once_with(None) | ||
| assert c._send_request.await_count == 2 | ||
| assert c._receive_packet.await_count == 2 | ||
| assert c._receive_packet.await_args_list[0][0][0].encode() == '2' | ||
| assert c._receive_packet.await_args_list[1][0][0].encode() == '6' | ||
| def test_read_loop_websocket_disconnected(self): | ||
| async def test_read_loop_websocket_disconnected(self): | ||
| c = async_client.AsyncClient() | ||
| c.state = 'disconnected' | ||
| c.write_loop_task = AsyncMock()() | ||
| _run(c._read_loop_websocket()) | ||
| c.write_loop_task = mock.AsyncMock()() | ||
| await c._read_loop_websocket() | ||
| # should not block | ||
| def test_read_loop_websocket_timeout(self): | ||
| async def test_read_loop_websocket_timeout(self): | ||
| c = async_client.AsyncClient() | ||
@@ -1186,11 +1177,11 @@ c.ping_interval = 1 | ||
| c.queue = mock.MagicMock() | ||
| c.queue.put = AsyncMock() | ||
| c.queue.put = mock.AsyncMock() | ||
| c.ws = mock.MagicMock() | ||
| c.ws.receive = AsyncMock(side_effect=asyncio.TimeoutError()) | ||
| c.write_loop_task = AsyncMock()() | ||
| _run(c._read_loop_websocket()) | ||
| c.ws.receive = mock.AsyncMock(side_effect=asyncio.TimeoutError()) | ||
| c.write_loop_task = mock.AsyncMock()() | ||
| await c._read_loop_websocket() | ||
| assert c.state == 'disconnected' | ||
| c.queue.put.mock.assert_called_once_with(None) | ||
| c.queue.put.assert_awaited_once_with(None) | ||
| def test_read_loop_websocket_no_response(self): | ||
| async def test_read_loop_websocket_no_response(self): | ||
| c = async_client.AsyncClient() | ||
@@ -1202,13 +1193,13 @@ c.ping_interval = 1 | ||
| c.queue = mock.MagicMock() | ||
| c.queue.put = AsyncMock() | ||
| c.queue.put = mock.AsyncMock() | ||
| c.ws = mock.MagicMock() | ||
| c.ws.receive = AsyncMock( | ||
| c.ws.receive = mock.AsyncMock( | ||
| side_effect=aiohttp.client_exceptions.ServerDisconnectedError() | ||
| ) | ||
| c.write_loop_task = AsyncMock()() | ||
| _run(c._read_loop_websocket()) | ||
| c.write_loop_task = mock.AsyncMock()() | ||
| await c._read_loop_websocket() | ||
| assert c.state == 'disconnected' | ||
| c.queue.put.mock.assert_called_once_with(None) | ||
| c.queue.put.assert_awaited_once_with(None) | ||
| def test_read_loop_websocket_unexpected_error(self): | ||
| async def test_read_loop_websocket_unexpected_error(self): | ||
| c = async_client.AsyncClient() | ||
@@ -1220,11 +1211,11 @@ c.ping_interval = 1 | ||
| c.queue = mock.MagicMock() | ||
| c.queue.put = AsyncMock() | ||
| c.queue.put = mock.AsyncMock() | ||
| c.ws = mock.MagicMock() | ||
| c.ws.receive = AsyncMock(side_effect=ValueError) | ||
| c.write_loop_task = AsyncMock()() | ||
| _run(c._read_loop_websocket()) | ||
| c.ws.receive = mock.AsyncMock(side_effect=ValueError) | ||
| c.write_loop_task = mock.AsyncMock()() | ||
| await c._read_loop_websocket() | ||
| assert c.state == 'disconnected' | ||
| c.queue.put.mock.assert_called_once_with(None) | ||
| c.queue.put.assert_awaited_once_with(None) | ||
| def test_read_loop_websocket(self): | ||
| async def test_read_loop_websocket(self): | ||
| c = async_client.AsyncClient() | ||
@@ -1236,5 +1227,5 @@ c.ping_interval = 1 | ||
| c.queue = mock.MagicMock() | ||
| c.queue.put = AsyncMock() | ||
| c.queue.put = mock.AsyncMock() | ||
| c.ws = mock.MagicMock() | ||
| c.ws.receive = AsyncMock( | ||
| c.ws.receive = mock.AsyncMock( | ||
| side_effect=[ | ||
@@ -1245,16 +1236,16 @@ mock.MagicMock(data=packet.Packet(packet.PING).encode()), | ||
| ) | ||
| c.write_loop_task = AsyncMock()() | ||
| c._receive_packet = AsyncMock() | ||
| _run(c._read_loop_websocket()) | ||
| c.write_loop_task = mock.AsyncMock()() | ||
| c._receive_packet = mock.AsyncMock() | ||
| await c._read_loop_websocket() | ||
| assert c.state == 'disconnected' | ||
| assert c._receive_packet.mock.call_args_list[0][0][0].encode() == '2' | ||
| c.queue.put.mock.assert_called_once_with(None) | ||
| assert c._receive_packet.await_args_list[0][0][0].encode() == '2' | ||
| c.queue.put.assert_awaited_once_with(None) | ||
| def test_write_loop_disconnected(self): | ||
| async def test_write_loop_disconnected(self): | ||
| c = async_client.AsyncClient() | ||
| c.state = 'disconnected' | ||
| _run(c._write_loop()) | ||
| await c._write_loop() | ||
| # should not block | ||
| def test_write_loop_no_packets(self): | ||
| async def test_write_loop_no_packets(self): | ||
| c = async_client.AsyncClient() | ||
@@ -1265,8 +1256,8 @@ c.state = 'connected' | ||
| c.queue = mock.MagicMock() | ||
| c.queue.get = AsyncMock(return_value=None) | ||
| _run(c._write_loop()) | ||
| c.queue.get = mock.AsyncMock(return_value=None) | ||
| await c._write_loop() | ||
| c.queue.task_done.assert_called_once_with() | ||
| c.queue.get.mock.assert_called_once_with() | ||
| c.queue.get.assert_awaited_once_with() | ||
| def test_write_loop_empty_queue(self): | ||
| async def test_write_loop_empty_queue(self): | ||
| c = async_client.AsyncClient() | ||
@@ -1278,7 +1269,7 @@ c.state = 'connected' | ||
| c.queue.Empty = RuntimeError | ||
| c.queue.get = AsyncMock(side_effect=RuntimeError) | ||
| _run(c._write_loop()) | ||
| c.queue.get.mock.assert_called_once_with() | ||
| c.queue.get = mock.AsyncMock(side_effect=RuntimeError) | ||
| await c._write_loop() | ||
| c.queue.get.assert_awaited_once_with() | ||
| def test_write_loop_polling_one_packet(self): | ||
| async def test_write_loop_polling_one_packet(self): | ||
| c = async_client.AsyncClient() | ||
@@ -1292,3 +1283,3 @@ c.base_url = 'http://foo' | ||
| c.queue.Empty = RuntimeError | ||
| c.queue.get = AsyncMock( | ||
| c.queue.get = mock.AsyncMock( | ||
| side_effect=[ | ||
@@ -1300,5 +1291,5 @@ packet.Packet(packet.MESSAGE, {'foo': 'bar'}), | ||
| c.queue.get_nowait = mock.MagicMock(side_effect=RuntimeError) | ||
| c._send_request = AsyncMock() | ||
| c._send_request.mock.return_value.status = 200 | ||
| _run(c._write_loop()) | ||
| c._send_request = mock.AsyncMock() | ||
| c._send_request.return_value.status = 200 | ||
| await c._write_loop() | ||
| assert c.queue.task_done.call_count == 1 | ||
@@ -1308,3 +1299,3 @@ p = payload.Payload( | ||
| ) | ||
| c._send_request.mock.assert_called_once_with( | ||
| c._send_request.assert_awaited_once_with( | ||
| 'POST', | ||
@@ -1317,3 +1308,3 @@ 'http://foo', | ||
| def test_write_loop_polling_three_packets(self): | ||
| async def test_write_loop_polling_three_packets(self): | ||
| c = async_client.AsyncClient() | ||
@@ -1327,3 +1318,3 @@ c.base_url = 'http://foo' | ||
| c.queue.Empty = RuntimeError | ||
| c.queue.get = AsyncMock( | ||
| c.queue.get = mock.AsyncMock( | ||
| side_effect=[ | ||
@@ -1341,5 +1332,5 @@ packet.Packet(packet.MESSAGE, {'foo': 'bar'}), | ||
| ) | ||
| c._send_request = AsyncMock() | ||
| c._send_request.mock.return_value.status = 200 | ||
| _run(c._write_loop()) | ||
| c._send_request = mock.AsyncMock() | ||
| c._send_request.return_value.status = 200 | ||
| await c._write_loop() | ||
| assert c.queue.task_done.call_count == 3 | ||
@@ -1353,3 +1344,3 @@ p = payload.Payload( | ||
| ) | ||
| c._send_request.mock.assert_called_once_with( | ||
| c._send_request.assert_awaited_once_with( | ||
| 'POST', | ||
@@ -1362,3 +1353,3 @@ 'http://foo', | ||
| def test_write_loop_polling_two_packets_done(self): | ||
| async def test_write_loop_polling_two_packets_done(self): | ||
| c = async_client.AsyncClient() | ||
@@ -1372,3 +1363,3 @@ c.base_url = 'http://foo' | ||
| c.queue.Empty = RuntimeError | ||
| c.queue.get = AsyncMock( | ||
| c.queue.get = mock.AsyncMock( | ||
| side_effect=[ | ||
@@ -1382,5 +1373,5 @@ packet.Packet(packet.MESSAGE, {'foo': 'bar'}), | ||
| ) | ||
| c._send_request = AsyncMock() | ||
| c._send_request.mock.return_value.status = 200 | ||
| _run(c._write_loop()) | ||
| c._send_request = mock.AsyncMock() | ||
| c._send_request.return_value.status = 200 | ||
| await c._write_loop() | ||
| assert c.queue.task_done.call_count == 3 | ||
@@ -1393,3 +1384,3 @@ p = payload.Payload( | ||
| ) | ||
| c._send_request.mock.assert_called_once_with( | ||
| c._send_request.assert_awaited_once_with( | ||
| 'POST', | ||
@@ -1403,3 +1394,3 @@ 'http://foo', | ||
| def test_write_loop_polling_bad_connection(self): | ||
| async def test_write_loop_polling_bad_connection(self): | ||
| c = async_client.AsyncClient() | ||
@@ -1413,8 +1404,8 @@ c.base_url = 'http://foo' | ||
| c.queue.Empty = RuntimeError | ||
| c.queue.get = AsyncMock( | ||
| c.queue.get = mock.AsyncMock( | ||
| side_effect=[packet.Packet(packet.MESSAGE, {'foo': 'bar'})] | ||
| ) | ||
| c.queue.get_nowait = mock.MagicMock(side_effect=[RuntimeError]) | ||
| c._send_request = AsyncMock(return_value=None) | ||
| _run(c._write_loop()) | ||
| c._send_request = mock.AsyncMock(return_value=None) | ||
| await c._write_loop() | ||
| assert c.queue.task_done.call_count == 1 | ||
@@ -1424,3 +1415,3 @@ p = payload.Payload( | ||
| ) | ||
| c._send_request.mock.assert_called_once_with( | ||
| c._send_request.assert_awaited_once_with( | ||
| 'POST', | ||
@@ -1434,3 +1425,3 @@ 'http://foo', | ||
| def test_write_loop_polling_bad_status(self): | ||
| async def test_write_loop_polling_bad_status(self): | ||
| c = async_client.AsyncClient() | ||
@@ -1444,9 +1435,9 @@ c.base_url = 'http://foo' | ||
| c.queue.Empty = RuntimeError | ||
| c.queue.get = AsyncMock( | ||
| c.queue.get = mock.AsyncMock( | ||
| side_effect=[packet.Packet(packet.MESSAGE, {'foo': 'bar'})] | ||
| ) | ||
| c.queue.get_nowait = mock.MagicMock(side_effect=[RuntimeError]) | ||
| c._send_request = AsyncMock() | ||
| c._send_request.mock.return_value.status = 500 | ||
| _run(c._write_loop()) | ||
| c._send_request = mock.AsyncMock() | ||
| c._send_request.return_value.status = 500 | ||
| await c._write_loop() | ||
| assert c.queue.task_done.call_count == 1 | ||
@@ -1456,3 +1447,3 @@ p = payload.Payload( | ||
| ) | ||
| c._send_request.mock.assert_called_once_with( | ||
| c._send_request.assert_awaited_once_with( | ||
| 'POST', | ||
@@ -1467,3 +1458,3 @@ 'http://foo', | ||
| def test_write_loop_websocket_one_packet(self): | ||
| async def test_write_loop_websocket_one_packet(self): | ||
| c = async_client.AsyncClient() | ||
@@ -1476,3 +1467,3 @@ c.state = 'connected' | ||
| c.queue.Empty = RuntimeError | ||
| c.queue.get = AsyncMock( | ||
| c.queue.get = mock.AsyncMock( | ||
| side_effect=[ | ||
@@ -1485,9 +1476,9 @@ packet.Packet(packet.MESSAGE, {'foo': 'bar'}), | ||
| c.ws = mock.MagicMock() | ||
| c.ws.send_str = AsyncMock() | ||
| _run(c._write_loop()) | ||
| c.ws.send_str = mock.AsyncMock() | ||
| await c._write_loop() | ||
| assert c.queue.task_done.call_count == 1 | ||
| assert c.ws.send_str.mock.call_count == 1 | ||
| c.ws.send_str.mock.assert_called_once_with('4{"foo":"bar"}') | ||
| assert c.ws.send_str.await_count == 1 | ||
| c.ws.send_str.assert_awaited_once_with('4{"foo":"bar"}') | ||
| def test_write_loop_websocket_three_packets(self): | ||
| async def test_write_loop_websocket_three_packets(self): | ||
| c = async_client.AsyncClient() | ||
@@ -1500,3 +1491,3 @@ c.state = 'connected' | ||
| c.queue.Empty = RuntimeError | ||
| c.queue.get = AsyncMock( | ||
| c.queue.get = mock.AsyncMock( | ||
| side_effect=[ | ||
@@ -1515,11 +1506,11 @@ packet.Packet(packet.MESSAGE, {'foo': 'bar'}), | ||
| c.ws = mock.MagicMock() | ||
| c.ws.send_str = AsyncMock() | ||
| _run(c._write_loop()) | ||
| c.ws.send_str = mock.AsyncMock() | ||
| await c._write_loop() | ||
| assert c.queue.task_done.call_count == 3 | ||
| assert c.ws.send_str.mock.call_count == 3 | ||
| assert c.ws.send_str.mock.call_args_list[0][0][0] == '4{"foo":"bar"}' | ||
| assert c.ws.send_str.mock.call_args_list[1][0][0] == '2' | ||
| assert c.ws.send_str.mock.call_args_list[2][0][0] == '6' | ||
| assert c.ws.send_str.await_count == 3 | ||
| assert c.ws.send_str.await_args_list[0][0][0] == '4{"foo":"bar"}' | ||
| assert c.ws.send_str.await_args_list[1][0][0] == '2' | ||
| assert c.ws.send_str.await_args_list[2][0][0] == '6' | ||
| def test_write_loop_websocket_one_packet_binary(self): | ||
| async def test_write_loop_websocket_one_packet_binary(self): | ||
| c = async_client.AsyncClient() | ||
@@ -1532,3 +1523,3 @@ c.state = 'connected' | ||
| c.queue.Empty = RuntimeError | ||
| c.queue.get = AsyncMock( | ||
| c.queue.get = mock.AsyncMock( | ||
| side_effect=[packet.Packet(packet.MESSAGE, b'foo'), RuntimeError] | ||
@@ -1538,9 +1529,9 @@ ) | ||
| c.ws = mock.MagicMock() | ||
| c.ws.send_bytes = AsyncMock() | ||
| _run(c._write_loop()) | ||
| c.ws.send_bytes = mock.AsyncMock() | ||
| await c._write_loop() | ||
| assert c.queue.task_done.call_count == 1 | ||
| assert c.ws.send_bytes.mock.call_count == 1 | ||
| c.ws.send_bytes.mock.assert_called_once_with(b'foo') | ||
| assert c.ws.send_bytes.await_count == 1 | ||
| c.ws.send_bytes.assert_awaited_once_with(b'foo') | ||
| def test_write_loop_websocket_bad_connection(self): | ||
| async def test_write_loop_websocket_bad_connection(self): | ||
| c = async_client.AsyncClient() | ||
@@ -1553,3 +1544,3 @@ c.state = 'connected' | ||
| c.queue.Empty = RuntimeError | ||
| c.queue.get = AsyncMock( | ||
| c.queue.get = mock.AsyncMock( | ||
| side_effect=[ | ||
@@ -1562,10 +1553,10 @@ packet.Packet(packet.MESSAGE, {'foo': 'bar'}), | ||
| c.ws = mock.MagicMock() | ||
| c.ws.send_str = AsyncMock( | ||
| c.ws.send_str = mock.AsyncMock( | ||
| side_effect=aiohttp.client_exceptions.ServerDisconnectedError() | ||
| ) | ||
| _run(c._write_loop()) | ||
| await c._write_loop() | ||
| assert c.state == 'connected' | ||
| @mock.patch('engineio.base_client.original_signal_handler') | ||
| def test_signal_handler(self, original_handler): | ||
| async def test_signal_handler(self, original_handler): | ||
| clients = [mock.MagicMock(), mock.MagicMock()] | ||
@@ -1575,8 +1566,9 @@ base_client.connected_clients = clients[:] | ||
| base_client.connected_clients[1].is_asyncio_based.return_value = True | ||
| base_client.connected_clients[1].disconnect = mock.AsyncMock() | ||
| async def test(): | ||
| async_client.async_signal_handler() | ||
| async_client.async_signal_handler() | ||
| with pytest.raises(asyncio.CancelledError): | ||
| await asyncio.sleep(0) | ||
| asyncio.get_event_loop().run_until_complete(test()) | ||
| clients[0].disconnect.assert_not_called() | ||
| clients[1].disconnect.assert_called_once_with() |
+239
-219
@@ -5,3 +5,2 @@ import asyncio | ||
| import logging | ||
| import unittest | ||
| from unittest import mock | ||
@@ -20,19 +19,3 @@ import zlib | ||
| def AsyncMock(*args, **kwargs): | ||
| """Return a mock asynchronous function.""" | ||
| m = mock.MagicMock(*args, **kwargs) | ||
| async def mock_coro(*args, **kwargs): | ||
| return m(*args, **kwargs) | ||
| mock_coro.mock = m | ||
| return mock_coro | ||
| def _run(coro): | ||
| """Run the given coroutine.""" | ||
| return asyncio.get_event_loop().run_until_complete(coro) | ||
| class TestAsyncServer(unittest.TestCase): | ||
| class TestAsyncServer: | ||
| @staticmethod | ||
@@ -63,7 +46,7 @@ def get_async_mock(environ={'REQUEST_METHOD': 'GET', 'QUERY_STRING': ''}): | ||
| mock_socket.upgraded = False | ||
| mock_socket.send = AsyncMock() | ||
| mock_socket.handle_get_request = AsyncMock() | ||
| mock_socket.handle_post_request = AsyncMock() | ||
| mock_socket.check_ping_timeout = AsyncMock() | ||
| mock_socket.close = AsyncMock() | ||
| mock_socket.send = mock.AsyncMock() | ||
| mock_socket.handle_get_request = mock.AsyncMock() | ||
| mock_socket.handle_post_request = mock.AsyncMock() | ||
| mock_socket.check_ping_timeout = mock.AsyncMock() | ||
| mock_socket.close = mock.AsyncMock() | ||
| mock_socket.session = {} | ||
@@ -73,25 +56,25 @@ return mock_socket | ||
| @classmethod | ||
| def setUpClass(cls): | ||
| def setup_class(cls): | ||
| async_server.AsyncServer._default_monitor_clients = False | ||
| @classmethod | ||
| def tearDownClass(cls): | ||
| def teardown_class(cls): | ||
| async_server.AsyncServer._default_monitor_clients = True | ||
| def setUp(self): | ||
| def setup_method(self): | ||
| logging.getLogger('engineio').setLevel(logging.NOTSET) | ||
| def tearDown(self): | ||
| def teardown_method(self): | ||
| # restore JSON encoder, in case a test changed it | ||
| packet.Packet.json = json | ||
| def test_is_asyncio_based(self): | ||
| async def test_is_asyncio_based(self): | ||
| s = async_server.AsyncServer() | ||
| assert s.is_asyncio_based() | ||
| def test_async_modes(self): | ||
| async def test_async_modes(self): | ||
| s = async_server.AsyncServer() | ||
| assert s.async_modes() == ['aiohttp', 'sanic', 'tornado', 'asgi'] | ||
| def test_async_mode_aiohttp(self): | ||
| async def test_async_mode_aiohttp(self): | ||
| s = async_server.AsyncServer(async_mode='aiohttp') | ||
@@ -106,3 +89,3 @@ assert s.async_mode == 'aiohttp' | ||
| @mock.patch('importlib.import_module') | ||
| def test_async_mode_auto_aiohttp(self, import_module): | ||
| async def test_async_mode_auto_aiohttp(self, import_module): | ||
| import_module.side_effect = [self.get_async_mock()] | ||
@@ -112,3 +95,3 @@ s = async_server.AsyncServer() | ||
| def test_async_modes_wsgi(self): | ||
| async def test_async_modes_wsgi(self): | ||
| with pytest.raises(ValueError): | ||
@@ -124,3 +107,3 @@ async_server.AsyncServer(async_mode='eventlet') | ||
| @mock.patch('importlib.import_module') | ||
| def test_attach(self, import_module): | ||
| async def test_attach(self, import_module): | ||
| a = self.get_async_mock() | ||
@@ -138,3 +121,3 @@ import_module.side_effect = [a] | ||
| def test_session(self): | ||
| async def test_session(self): | ||
| s = async_server.AsyncServer() | ||
@@ -149,21 +132,24 @@ s.sockets['foo'] = self._get_mock_socket() | ||
| _run(_func()) | ||
| await _func() | ||
| def test_disconnect(self): | ||
| async def test_disconnect(self): | ||
| s = async_server.AsyncServer() | ||
| s.sockets['foo'] = mock_socket = self._get_mock_socket() | ||
| _run(s.disconnect('foo')) | ||
| assert mock_socket.close.mock.call_count == 1 | ||
| mock_socket.close.mock.assert_called_once_with() | ||
| await s.disconnect('foo') | ||
| assert mock_socket.close.await_count == 1 | ||
| mock_socket.close.assert_awaited_once_with( | ||
| reason=s.reason.SERVER_DISCONNECT) | ||
| assert 'foo' not in s.sockets | ||
| def test_disconnect_all(self): | ||
| async def test_disconnect_all(self): | ||
| s = async_server.AsyncServer() | ||
| s.sockets['foo'] = mock_foo = self._get_mock_socket() | ||
| s.sockets['bar'] = mock_bar = self._get_mock_socket() | ||
| _run(s.disconnect()) | ||
| assert mock_foo.close.mock.call_count == 1 | ||
| assert mock_bar.close.mock.call_count == 1 | ||
| mock_foo.close.mock.assert_called_once_with() | ||
| mock_bar.close.mock.assert_called_once_with() | ||
| await s.disconnect() | ||
| assert mock_foo.close.await_count == 1 | ||
| assert mock_bar.close.await_count == 1 | ||
| mock_foo.close.assert_awaited_once_with( | ||
| reason=s.reason.SERVER_DISCONNECT) | ||
| mock_bar.close.assert_awaited_once_with( | ||
| reason=s.reason.SERVER_DISCONNECT) | ||
| assert 'foo' not in s.sockets | ||
@@ -173,3 +159,3 @@ assert 'bar' not in s.sockets | ||
| @mock.patch('importlib.import_module') | ||
| def test_jsonp_not_supported(self, import_module): | ||
| async def test_jsonp_not_supported(self, import_module): | ||
| a = self.get_async_mock( | ||
@@ -180,3 +166,3 @@ {'REQUEST_METHOD': 'GET', 'QUERY_STRING': 'j=abc'} | ||
| s = async_server.AsyncServer() | ||
| response = _run(s.handle_request('request')) | ||
| response = await s.handle_request('request') | ||
| assert response == 'response' | ||
@@ -188,3 +174,3 @@ a._async['translate_request'].assert_called_once_with('request') | ||
| @mock.patch('importlib.import_module') | ||
| def test_jsonp_index(self, import_module): | ||
| async def test_jsonp_index(self, import_module): | ||
| a = self.get_async_mock( | ||
@@ -195,3 +181,3 @@ {'REQUEST_METHOD': 'GET', 'QUERY_STRING': 'j=233'} | ||
| s = async_server.AsyncServer() | ||
| response = _run(s.handle_request('request')) | ||
| response = await s.handle_request('request') | ||
| assert response == 'response' | ||
@@ -209,7 +195,7 @@ a._async['translate_request'].assert_called_once_with('request') | ||
| @mock.patch('importlib.import_module') | ||
| def test_connect(self, import_module): | ||
| async def test_connect(self, import_module): | ||
| a = self.get_async_mock() | ||
| import_module.side_effect = [a] | ||
| s = async_server.AsyncServer() | ||
| _run(s.handle_request('request')) | ||
| await s.handle_request('request') | ||
| assert len(s.sockets) == 1 | ||
@@ -229,10 +215,14 @@ assert a._async['make_response'].call_count == 1 | ||
| assert 'sid' in packets[0].data | ||
| assert packets[0].data['pingTimeout'] == 20000 | ||
| assert packets[0].data['pingInterval'] == 25000 | ||
| assert packets[0].data['maxPayload'] == 1000000 | ||
| @mock.patch('importlib.import_module') | ||
| def test_connect_async_request_response_handlers(self, import_module): | ||
| async def test_connect_async_request_response_handlers( | ||
| self, import_module): | ||
| a = self.get_async_mock() | ||
| a._async['translate_request'] = AsyncMock( | ||
| a._async['translate_request'] = mock.AsyncMock( | ||
| return_value=a._async['translate_request'].return_value | ||
| ) | ||
| a._async['make_response'] = AsyncMock( | ||
| a._async['make_response'] = mock.AsyncMock( | ||
| return_value=a._async['make_response'].return_value | ||
@@ -242,11 +232,11 @@ ) | ||
| s = async_server.AsyncServer() | ||
| _run(s.handle_request('request')) | ||
| await s.handle_request('request') | ||
| assert len(s.sockets) == 1 | ||
| assert a._async['make_response'].mock.call_count == 1 | ||
| assert a._async['make_response'].mock.call_args[0][0] == '200 OK' | ||
| assert a._async['make_response'].await_count == 1 | ||
| assert a._async['make_response'].await_args[0][0] == '200 OK' | ||
| assert ('Content-Type', 'text/plain; charset=UTF-8') in a._async[ | ||
| 'make_response' | ||
| ].mock.call_args[0][1] | ||
| ].await_args[0][1] | ||
| packets = payload.Payload( | ||
| encoded_payload=a._async['make_response'].mock.call_args[0][ | ||
| encoded_payload=a._async['make_response'].await_args[0][ | ||
| 2].decode('utf-8')).packets | ||
@@ -260,7 +250,7 @@ assert len(packets) == 1 | ||
| @mock.patch('importlib.import_module') | ||
| def test_connect_no_upgrades(self, import_module): | ||
| async def test_connect_no_upgrades(self, import_module): | ||
| a = self.get_async_mock() | ||
| import_module.side_effect = [a] | ||
| s = async_server.AsyncServer(allow_upgrades=False) | ||
| _run(s.handle_request('request')) | ||
| await s.handle_request('request') | ||
| packets = payload.Payload( | ||
@@ -272,3 +262,3 @@ encoded_payload=a._async['make_response'].call_args[0][2].decode( | ||
| @mock.patch('importlib.import_module') | ||
| def test_connect_bad_eio_version(self, import_module): | ||
| async def test_connect_bad_eio_version(self, import_module): | ||
| a = self.get_async_mock( | ||
@@ -279,3 +269,3 @@ {'REQUEST_METHOD': 'GET', 'QUERY_STRING': 'EIO=1'} | ||
| s = async_server.AsyncServer() | ||
| _run(s.handle_request('request')) | ||
| await s.handle_request('request') | ||
| assert a._async['make_response'].call_count == 1 | ||
@@ -287,7 +277,8 @@ assert a._async['make_response'].call_args[0][0] == '400 BAD REQUEST' | ||
| @mock.patch('importlib.import_module') | ||
| def test_connect_custom_ping_times(self, import_module): | ||
| async def test_connect_custom_ping_times(self, import_module): | ||
| a = self.get_async_mock() | ||
| import_module.side_effect = [a] | ||
| s = async_server.AsyncServer(ping_timeout=123, ping_interval=456) | ||
| _run(s.handle_request('request')) | ||
| s = async_server.AsyncServer(ping_timeout=123, ping_interval=456, | ||
| max_http_buffer_size=12345678) | ||
| await s.handle_request('request') | ||
| packets = payload.Payload( | ||
@@ -298,6 +289,7 @@ encoded_payload=a._async['make_response'].call_args[0][2].decode( | ||
| assert packets[0].data['pingInterval'] == 456000 | ||
| assert packets[0].data['maxPayload'] == 12345678 | ||
| @mock.patch('importlib.import_module') | ||
| @mock.patch('engineio.async_server.async_socket.AsyncSocket') | ||
| def test_connect_bad_poll(self, AsyncSocket, import_module): | ||
| async def test_connect_bad_poll(self, AsyncSocket, import_module): | ||
| a = self.get_async_mock() | ||
@@ -308,3 +300,3 @@ import_module.side_effect = [a] | ||
| s = async_server.AsyncServer() | ||
| _run(s.handle_request('request')) | ||
| await s.handle_request('request') | ||
| assert a._async['make_response'].call_count == 1 | ||
@@ -315,3 +307,4 @@ assert a._async['make_response'].call_args[0][0] == '400 BAD REQUEST' | ||
| @mock.patch('engineio.async_server.async_socket.AsyncSocket') | ||
| def test_connect_transport_websocket(self, AsyncSocket, import_module): | ||
| async def test_connect_transport_websocket(self, AsyncSocket, | ||
| import_module): | ||
| a = self.get_async_mock( | ||
@@ -330,5 +323,5 @@ { | ||
| AsyncSocket().closed = False | ||
| _run(s.handle_request('request')) | ||
| await s.handle_request('request') | ||
| assert ( | ||
| s.sockets['123'].send.mock.call_args[0][0].packet_type | ||
| s.sockets['123'].send.await_args[0][0].packet_type | ||
| == packet.OPEN | ||
@@ -339,3 +332,4 @@ ) | ||
| @mock.patch('engineio.async_server.async_socket.AsyncSocket') | ||
| def test_http_upgrade_case_insensitive(self, AsyncSocket, import_module): | ||
| async def test_http_upgrade_case_insensitive(self, AsyncSocket, | ||
| import_module): | ||
| a = self.get_async_mock( | ||
@@ -354,5 +348,5 @@ { | ||
| AsyncSocket().closed = False | ||
| _run(s.handle_request('request')) | ||
| await s.handle_request('request') | ||
| assert ( | ||
| s.sockets['123'].send.mock.call_args[0][0].packet_type | ||
| s.sockets['123'].send.await_args[0][0].packet_type | ||
| == packet.OPEN | ||
@@ -363,3 +357,3 @@ ) | ||
| @mock.patch('engineio.async_server.async_socket.AsyncSocket') | ||
| def test_connect_transport_websocket_closed( | ||
| async def test_connect_transport_websocket_closed( | ||
| self, AsyncSocket, import_module): | ||
@@ -384,7 +378,7 @@ a = self.get_async_mock( | ||
| AsyncSocket().handle_get_request = mock_handle | ||
| _run(s.handle_request('request')) | ||
| await s.handle_request('request') | ||
| assert '123' not in s.sockets # socket should close on its own | ||
| @mock.patch('importlib.import_module') | ||
| def test_connect_transport_invalid(self, import_module): | ||
| async def test_connect_transport_invalid(self, import_module): | ||
| a = self.get_async_mock( | ||
@@ -395,3 +389,3 @@ {'REQUEST_METHOD': 'GET', 'QUERY_STRING': 'transport=foo'} | ||
| s = async_server.AsyncServer() | ||
| _run(s.handle_request('request')) | ||
| await s.handle_request('request') | ||
| assert a._async['make_response'].call_count == 1 | ||
@@ -401,3 +395,4 @@ assert a._async['make_response'].call_args[0][0] == '400 BAD REQUEST' | ||
| @mock.patch('importlib.import_module') | ||
| def test_connect_transport_websocket_without_upgrade(self, import_module): | ||
| async def test_connect_transport_websocket_without_upgrade( | ||
| self, import_module): | ||
| a = self.get_async_mock( | ||
@@ -408,3 +403,3 @@ {'REQUEST_METHOD': 'GET', 'QUERY_STRING': 'transport=websocket'} | ||
| s = async_server.AsyncServer() | ||
| _run(s.handle_request('request')) | ||
| await s.handle_request('request') | ||
| assert a._async['make_response'].call_count == 1 | ||
@@ -414,7 +409,7 @@ assert a._async['make_response'].call_args[0][0] == '400 BAD REQUEST' | ||
| @mock.patch('importlib.import_module') | ||
| def test_connect_cors_headers(self, import_module): | ||
| async def test_connect_cors_headers(self, import_module): | ||
| a = self.get_async_mock() | ||
| import_module.side_effect = [a] | ||
| s = async_server.AsyncServer() | ||
| _run(s.handle_request('request')) | ||
| await s.handle_request('request') | ||
| assert a._async['make_response'].call_args[0][0] == '200 OK' | ||
@@ -425,3 +420,3 @@ headers = a._async['make_response'].call_args[0][1] | ||
| @mock.patch('importlib.import_module') | ||
| def test_connect_cors_allowed_origin(self, import_module): | ||
| async def test_connect_cors_allowed_origin(self, import_module): | ||
| a = self.get_async_mock( | ||
@@ -432,3 +427,3 @@ {'REQUEST_METHOD': 'GET', 'QUERY_STRING': '', 'HTTP_ORIGIN': 'b'} | ||
| s = async_server.AsyncServer(cors_allowed_origins=['a', 'b']) | ||
| _run(s.handle_request('request')) | ||
| await s.handle_request('request') | ||
| assert a._async['make_response'].call_args[0][0] == '200 OK' | ||
@@ -439,3 +434,4 @@ headers = a._async['make_response'].call_args[0][1] | ||
| @mock.patch('importlib.import_module') | ||
| def test_connect_cors_allowed_origin_with_callable(self, import_module): | ||
| async def test_connect_cors_allowed_origin_with_callable( | ||
| self, import_module): | ||
| def cors(origin): | ||
@@ -453,3 +449,3 @@ return origin == 'a' | ||
| s = async_server.AsyncServer(cors_allowed_origins=cors) | ||
| _run(s.handle_request('request')) | ||
| await s.handle_request('request') | ||
| assert a._async['make_response'].call_args[0][0] == '200 OK' | ||
@@ -460,7 +456,7 @@ headers = a._async['make_response'].call_args[0][1] | ||
| environ['HTTP_ORIGIN'] = 'b' | ||
| _run(s.handle_request('request')) | ||
| await s.handle_request('request') | ||
| assert a._async['make_response'].call_args[0][0] == '400 BAD REQUEST' | ||
| @mock.patch('importlib.import_module') | ||
| def test_connect_cors_not_allowed_origin(self, import_module): | ||
| async def test_connect_cors_not_allowed_origin(self, import_module): | ||
| a = self.get_async_mock( | ||
@@ -471,3 +467,3 @@ {'REQUEST_METHOD': 'GET', 'QUERY_STRING': '', 'HTTP_ORIGIN': 'c'} | ||
| s = async_server.AsyncServer(cors_allowed_origins=['a', 'b']) | ||
| _run(s.handle_request('request')) | ||
| await s.handle_request('request') | ||
| assert a._async['make_response'].call_args[0][0] == '400 BAD REQUEST' | ||
@@ -479,3 +475,3 @@ headers = a._async['make_response'].call_args[0][1] | ||
| @mock.patch('importlib.import_module') | ||
| def test_connect_cors_not_allowed_origin_async_response( | ||
| async def test_connect_cors_not_allowed_origin_async_response( | ||
| self, import_module | ||
@@ -486,3 +482,3 @@ ): | ||
| ) | ||
| a._async['make_response'] = AsyncMock( | ||
| a._async['make_response'] = mock.AsyncMock( | ||
| return_value=a._async['make_response'].return_value | ||
@@ -492,7 +488,7 @@ ) | ||
| s = async_server.AsyncServer(cors_allowed_origins=['a', 'b']) | ||
| _run(s.handle_request('request')) | ||
| await s.handle_request('request') | ||
| assert ( | ||
| a._async['make_response'].mock.call_args[0][0] == '400 BAD REQUEST' | ||
| a._async['make_response'].await_args[0][0] == '400 BAD REQUEST' | ||
| ) | ||
| headers = a._async['make_response'].mock.call_args[0][1] | ||
| headers = a._async['make_response'].await_args[0][1] | ||
| assert ('Access-Control-Allow-Origin', 'c') not in headers | ||
@@ -502,3 +498,3 @@ assert ('Access-Control-Allow-Origin', '*') not in headers | ||
| @mock.patch('importlib.import_module') | ||
| def test_connect_cors_all_origins(self, import_module): | ||
| async def test_connect_cors_all_origins(self, import_module): | ||
| a = self.get_async_mock( | ||
@@ -509,3 +505,3 @@ {'REQUEST_METHOD': 'GET', 'QUERY_STRING': '', 'HTTP_ORIGIN': 'foo'} | ||
| s = async_server.AsyncServer(cors_allowed_origins='*') | ||
| _run(s.handle_request('request')) | ||
| await s.handle_request('request') | ||
| assert a._async['make_response'].call_args[0][0] == '200 OK' | ||
@@ -517,3 +513,3 @@ headers = a._async['make_response'].call_args[0][1] | ||
| @mock.patch('importlib.import_module') | ||
| def test_connect_cors_one_origin(self, import_module): | ||
| async def test_connect_cors_one_origin(self, import_module): | ||
| a = self.get_async_mock( | ||
@@ -524,3 +520,3 @@ {'REQUEST_METHOD': 'GET', 'QUERY_STRING': '', 'HTTP_ORIGIN': 'a'} | ||
| s = async_server.AsyncServer(cors_allowed_origins='a') | ||
| _run(s.handle_request('request')) | ||
| await s.handle_request('request') | ||
| assert a._async['make_response'].call_args[0][0] == '200 OK' | ||
@@ -532,3 +528,3 @@ headers = a._async['make_response'].call_args[0][1] | ||
| @mock.patch('importlib.import_module') | ||
| def test_connect_cors_one_origin_not_allowed(self, import_module): | ||
| async def test_connect_cors_one_origin_not_allowed(self, import_module): | ||
| a = self.get_async_mock( | ||
@@ -539,3 +535,3 @@ {'REQUEST_METHOD': 'GET', 'QUERY_STRING': '', 'HTTP_ORIGIN': 'b'} | ||
| s = async_server.AsyncServer(cors_allowed_origins='a') | ||
| _run(s.handle_request('request')) | ||
| await s.handle_request('request') | ||
| assert a._async['make_response'].call_args[0][0] == '400 BAD REQUEST' | ||
@@ -547,3 +543,3 @@ headers = a._async['make_response'].call_args[0][1] | ||
| @mock.patch('importlib.import_module') | ||
| def test_connect_cors_headers_default_origin(self, import_module): | ||
| async def test_connect_cors_headers_default_origin(self, import_module): | ||
| a = self.get_async_mock( | ||
@@ -560,3 +556,3 @@ { | ||
| s = async_server.AsyncServer() | ||
| _run(s.handle_request('request')) | ||
| await s.handle_request('request') | ||
| assert a._async['make_response'].call_args[0][0] == '200 OK' | ||
@@ -567,7 +563,7 @@ headers = a._async['make_response'].call_args[0][1] | ||
| @mock.patch('importlib.import_module') | ||
| def test_connect_cors_no_credentials(self, import_module): | ||
| async def test_connect_cors_no_credentials(self, import_module): | ||
| a = self.get_async_mock() | ||
| import_module.side_effect = [a] | ||
| s = async_server.AsyncServer(cors_credentials=False) | ||
| _run(s.handle_request('request')) | ||
| await s.handle_request('request') | ||
| assert a._async['make_response'].call_args[0][0] == '200 OK' | ||
@@ -578,3 +574,3 @@ headers = a._async['make_response'].call_args[0][1] | ||
| @mock.patch('importlib.import_module') | ||
| def test_connect_cors_options(self, import_module): | ||
| async def test_connect_cors_options(self, import_module): | ||
| a = self.get_async_mock( | ||
@@ -585,3 +581,3 @@ {'REQUEST_METHOD': 'OPTIONS', 'QUERY_STRING': ''} | ||
| s = async_server.AsyncServer(cors_credentials=False) | ||
| _run(s.handle_request('request')) | ||
| await s.handle_request('request') | ||
| assert a._async['make_response'].call_args[0][0] == '200 OK' | ||
@@ -595,3 +591,3 @@ headers = a._async['make_response'].call_args[0][1] | ||
| @mock.patch('importlib.import_module') | ||
| def test_connect_cors_disabled(self, import_module): | ||
| async def test_connect_cors_disabled(self, import_module): | ||
| a = self.get_async_mock( | ||
@@ -606,3 +602,3 @@ { | ||
| s = async_server.AsyncServer(cors_allowed_origins=[]) | ||
| _run(s.handle_request('request')) | ||
| await s.handle_request('request') | ||
| assert a._async['make_response'].call_args[0][0] == '200 OK' | ||
@@ -614,7 +610,7 @@ headers = a._async['make_response'].call_args[0][1] | ||
| @mock.patch('importlib.import_module') | ||
| def test_connect_cors_default_no_origin(self, import_module): | ||
| async def test_connect_cors_default_no_origin(self, import_module): | ||
| a = self.get_async_mock({'REQUEST_METHOD': 'GET', 'QUERY_STRING': ''}) | ||
| import_module.side_effect = [a] | ||
| s = async_server.AsyncServer(cors_allowed_origins=[]) | ||
| _run(s.handle_request('request')) | ||
| await s.handle_request('request') | ||
| assert a._async['make_response'].call_args[0][0] == '200 OK' | ||
@@ -626,7 +622,7 @@ headers = a._async['make_response'].call_args[0][1] | ||
| @mock.patch('importlib.import_module') | ||
| def test_connect_cors_all_no_origin(self, import_module): | ||
| async def test_connect_cors_all_no_origin(self, import_module): | ||
| a = self.get_async_mock({'REQUEST_METHOD': 'GET', 'QUERY_STRING': ''}) | ||
| import_module.side_effect = [a] | ||
| s = async_server.AsyncServer(cors_allowed_origins='*') | ||
| _run(s.handle_request('request')) | ||
| await s.handle_request('request') | ||
| assert a._async['make_response'].call_args[0][0] == '200 OK' | ||
@@ -638,7 +634,7 @@ headers = a._async['make_response'].call_args[0][1] | ||
| @mock.patch('importlib.import_module') | ||
| def test_connect_cors_disabled_no_origin(self, import_module): | ||
| async def test_connect_cors_disabled_no_origin(self, import_module): | ||
| a = self.get_async_mock({'REQUEST_METHOD': 'GET', 'QUERY_STRING': ''}) | ||
| import_module.side_effect = [a] | ||
| s = async_server.AsyncServer(cors_allowed_origins=[]) | ||
| _run(s.handle_request('request')) | ||
| await s.handle_request('request') | ||
| assert a._async['make_response'].call_args[0][0] == '200 OK' | ||
@@ -650,3 +646,3 @@ headers = a._async['make_response'].call_args[0][1] | ||
| @mock.patch('importlib.import_module') | ||
| def test_connect_event(self, import_module): | ||
| async def test_connect_event(self, import_module): | ||
| a = self.get_async_mock() | ||
@@ -661,7 +657,7 @@ import_module.side_effect = [a] | ||
| s.on('connect', handler=mock_connect) | ||
| _run(s.handle_request('request')) | ||
| await s.handle_request('request') | ||
| assert len(s.sockets) == 1 | ||
| @mock.patch('importlib.import_module') | ||
| def test_connect_event_rejects(self, import_module): | ||
| async def test_connect_event_rejects(self, import_module): | ||
| a = self.get_async_mock() | ||
@@ -676,3 +672,3 @@ import_module.side_effect = [a] | ||
| s.on('connect')(mock_connect) | ||
| _run(s.handle_request('request')) | ||
| await s.handle_request('request') | ||
| assert len(s.sockets) == 0 | ||
@@ -683,3 +679,3 @@ assert a._async['make_response'].call_args[0][0] == '401 UNAUTHORIZED' | ||
| @mock.patch('importlib.import_module') | ||
| def test_connect_event_rejects_with_message(self, import_module): | ||
| async def test_connect_event_rejects_with_message(self, import_module): | ||
| a = self.get_async_mock() | ||
@@ -694,3 +690,3 @@ import_module.side_effect = [a] | ||
| s.on('connect')(mock_connect) | ||
| _run(s.handle_request('request')) | ||
| await s.handle_request('request') | ||
| assert len(s.sockets) == 0 | ||
@@ -703,7 +699,7 @@ assert a._async['make_response'].call_args[0][0] == '401 UNAUTHORIZED' | ||
| @mock.patch('importlib.import_module') | ||
| def test_method_not_found(self, import_module): | ||
| async def test_method_not_found(self, import_module): | ||
| a = self.get_async_mock({'REQUEST_METHOD': 'PUT', 'QUERY_STRING': ''}) | ||
| import_module.side_effect = [a] | ||
| s = async_server.AsyncServer() | ||
| _run(s.handle_request('request')) | ||
| await s.handle_request('request') | ||
| assert len(s.sockets) == 0 | ||
@@ -715,3 +711,3 @@ assert ( | ||
| @mock.patch('importlib.import_module') | ||
| def test_get_request_with_bad_sid(self, import_module): | ||
| async def test_get_request_with_bad_sid(self, import_module): | ||
| a = self.get_async_mock( | ||
@@ -722,3 +718,3 @@ {'REQUEST_METHOD': 'GET', 'QUERY_STRING': 'sid=foo'} | ||
| s = async_server.AsyncServer() | ||
| _run(s.handle_request('request')) | ||
| await s.handle_request('request') | ||
| assert len(s.sockets) == 0 | ||
@@ -728,3 +724,3 @@ assert a._async['make_response'].call_args[0][0] == '400 BAD REQUEST' | ||
| @mock.patch('importlib.import_module') | ||
| def test_get_request_bad_websocket_transport(self, import_module): | ||
| async def test_get_request_bad_websocket_transport(self, import_module): | ||
| a = self.get_async_mock( | ||
@@ -738,7 +734,7 @@ {'REQUEST_METHOD': 'GET', | ||
| mock_socket.upgraded = False | ||
| _run(s.handle_request('request')) | ||
| await s.handle_request('request') | ||
| assert a._async['make_response'].call_args[0][0] == '400 BAD REQUEST' | ||
| @mock.patch('importlib.import_module') | ||
| def test_get_request_bad_polling_transport(self, import_module): | ||
| async def test_get_request_bad_polling_transport(self, import_module): | ||
| a = self.get_async_mock( | ||
@@ -752,7 +748,7 @@ {'REQUEST_METHOD': 'GET', | ||
| mock_socket.upgraded = True | ||
| _run(s.handle_request('request')) | ||
| await s.handle_request('request') | ||
| assert a._async['make_response'].call_args[0][0] == '400 BAD REQUEST' | ||
| @mock.patch('importlib.import_module') | ||
| def test_post_request_with_bad_sid(self, import_module): | ||
| async def test_post_request_with_bad_sid(self, import_module): | ||
| a = self.get_async_mock( | ||
@@ -763,3 +759,3 @@ {'REQUEST_METHOD': 'POST', 'QUERY_STRING': 'sid=foo'} | ||
| s = async_server.AsyncServer() | ||
| _run(s.handle_request('request')) | ||
| await s.handle_request('request') | ||
| assert len(s.sockets) == 0 | ||
@@ -769,3 +765,3 @@ assert a._async['make_response'].call_args[0][0] == '400 BAD REQUEST' | ||
| @mock.patch('importlib.import_module') | ||
| def test_send(self, import_module): | ||
| async def test_send(self, import_module): | ||
| a = self.get_async_mock() | ||
@@ -775,11 +771,11 @@ import_module.side_effect = [a] | ||
| s.sockets['foo'] = mock_socket = self._get_mock_socket() | ||
| _run(s.send('foo', 'hello')) | ||
| assert mock_socket.send.mock.call_count == 1 | ||
| await s.send('foo', 'hello') | ||
| assert mock_socket.send.await_count == 1 | ||
| assert ( | ||
| mock_socket.send.mock.call_args[0][0].packet_type == packet.MESSAGE | ||
| mock_socket.send.await_args[0][0].packet_type == packet.MESSAGE | ||
| ) | ||
| assert mock_socket.send.mock.call_args[0][0].data == 'hello' | ||
| assert mock_socket.send.await_args[0][0].data == 'hello' | ||
| @mock.patch('importlib.import_module') | ||
| def test_send_unknown_socket(self, import_module): | ||
| async def test_send_unknown_socket(self, import_module): | ||
| a = self.get_async_mock() | ||
@@ -789,6 +785,6 @@ import_module.side_effect = [a] | ||
| # just ensure no exceptions are raised | ||
| _run(s.send('foo', 'hello')) | ||
| await s.send('foo', 'hello') | ||
| @mock.patch('importlib.import_module') | ||
| def test_get_request(self, import_module): | ||
| async def test_get_request(self, import_module): | ||
| a = self.get_async_mock( | ||
@@ -800,6 +796,6 @@ {'REQUEST_METHOD': 'GET', 'QUERY_STRING': 'sid=foo'} | ||
| s.sockets['foo'] = mock_socket = self._get_mock_socket() | ||
| mock_socket.handle_get_request.mock.return_value = [ | ||
| mock_socket.handle_get_request.return_value = [ | ||
| packet.Packet(packet.MESSAGE, data='hello') | ||
| ] | ||
| _run(s.handle_request('request')) | ||
| await s.handle_request('request') | ||
| assert a._async['make_response'].call_args[0][0] == '200 OK' | ||
@@ -814,3 +810,3 @@ packets = payload.Payload( | ||
| @mock.patch('importlib.import_module') | ||
| def test_get_request_custom_response(self, import_module): | ||
| async def test_get_request_custom_response(self, import_module): | ||
| a = self.get_async_mock( | ||
@@ -822,8 +818,8 @@ {'REQUEST_METHOD': 'GET', 'QUERY_STRING': 'sid=foo'} | ||
| s.sockets['foo'] = mock_socket = self._get_mock_socket() | ||
| mock_socket.handle_get_request.mock.return_value = 'resp' | ||
| r = _run(s.handle_request('request')) | ||
| mock_socket.handle_get_request.return_value = 'resp' | ||
| r = await s.handle_request('request') | ||
| assert r == 'resp' | ||
| @mock.patch('importlib.import_module') | ||
| def test_get_request_closes_socket(self, import_module): | ||
| async def test_get_request_closes_socket(self, import_module): | ||
| a = self.get_async_mock( | ||
@@ -841,3 +837,3 @@ {'REQUEST_METHOD': 'GET', 'QUERY_STRING': 'sid=foo'} | ||
| mock_socket.handle_get_request = mock_get_request | ||
| r = _run(s.handle_request('request')) | ||
| r = await s.handle_request('request') | ||
| assert r == 'resp' | ||
@@ -847,3 +843,3 @@ assert 'foo' not in s.sockets | ||
| @mock.patch('importlib.import_module') | ||
| def test_get_request_error(self, import_module): | ||
| async def test_get_request_error(self, import_module): | ||
| a = self.get_async_mock( | ||
@@ -860,3 +856,3 @@ {'REQUEST_METHOD': 'GET', 'QUERY_STRING': 'sid=foo'} | ||
| mock_socket.handle_get_request = mock_get_request | ||
| _run(s.handle_request('request')) | ||
| await s.handle_request('request') | ||
| assert a._async['make_response'].call_args[0][0] == '400 BAD REQUEST' | ||
@@ -866,3 +862,3 @@ assert len(s.sockets) == 0 | ||
| @mock.patch('importlib.import_module') | ||
| def test_post_request(self, import_module): | ||
| async def test_post_request(self, import_module): | ||
| a = self.get_async_mock( | ||
@@ -874,7 +870,7 @@ {'REQUEST_METHOD': 'POST', 'QUERY_STRING': 'sid=foo'} | ||
| s.sockets['foo'] = self._get_mock_socket() | ||
| _run(s.handle_request('request')) | ||
| await s.handle_request('request') | ||
| assert a._async['make_response'].call_args[0][0] == '200 OK' | ||
| @mock.patch('importlib.import_module') | ||
| def test_post_request_error(self, import_module): | ||
| async def test_post_request_error(self, import_module): | ||
| a = self.get_async_mock( | ||
@@ -891,3 +887,3 @@ {'REQUEST_METHOD': 'POST', 'QUERY_STRING': 'sid=foo'} | ||
| mock_socket.handle_post_request = mock_post_request | ||
| _run(s.handle_request('request')) | ||
| await s.handle_request('request') | ||
| assert a._async['make_response'].call_args[0][0] == '400 BAD REQUEST' | ||
@@ -902,3 +898,3 @@ | ||
| @mock.patch('importlib.import_module') | ||
| def test_gzip_compression(self, import_module): | ||
| async def test_gzip_compression(self, import_module): | ||
| a = self.get_async_mock( | ||
@@ -914,6 +910,6 @@ { | ||
| s.sockets['foo'] = mock_socket = self._get_mock_socket() | ||
| mock_socket.handle_get_request.mock.return_value = [ | ||
| mock_socket.handle_get_request.return_value = [ | ||
| packet.Packet(packet.MESSAGE, data='hello') | ||
| ] | ||
| _run(s.handle_request('request')) | ||
| await s.handle_request('request') | ||
| headers = a._async['make_response'].call_args[0][1] | ||
@@ -924,3 +920,3 @@ assert ('Content-Encoding', 'gzip') in headers | ||
| @mock.patch('importlib.import_module') | ||
| def test_deflate_compression(self, import_module): | ||
| async def test_deflate_compression(self, import_module): | ||
| a = self.get_async_mock( | ||
@@ -936,6 +932,6 @@ { | ||
| s.sockets['foo'] = mock_socket = self._get_mock_socket() | ||
| mock_socket.handle_get_request.mock.return_value = [ | ||
| mock_socket.handle_get_request.return_value = [ | ||
| packet.Packet(packet.MESSAGE, data='hello') | ||
| ] | ||
| _run(s.handle_request('request')) | ||
| await s.handle_request('request') | ||
| headers = a._async['make_response'].call_args[0][1] | ||
@@ -946,3 +942,3 @@ assert ('Content-Encoding', 'deflate') in headers | ||
| @mock.patch('importlib.import_module') | ||
| def test_gzip_compression_threshold(self, import_module): | ||
| async def test_gzip_compression_threshold(self, import_module): | ||
| a = self.get_async_mock( | ||
@@ -958,6 +954,6 @@ { | ||
| s.sockets['foo'] = mock_socket = self._get_mock_socket() | ||
| mock_socket.handle_get_request.mock.return_value = [ | ||
| mock_socket.handle_get_request.return_value = [ | ||
| packet.Packet(packet.MESSAGE, data='hello') | ||
| ] | ||
| _run(s.handle_request('request')) | ||
| await s.handle_request('request') | ||
| headers = a._async['make_response'].call_args[0][1] | ||
@@ -967,6 +963,7 @@ for header, value in headers: | ||
| with pytest.raises(IOError): | ||
| print(a._async['make_response'].call_args[0][2]) | ||
| self._gzip_decompress(a._async['make_response'].call_args[0][2]) | ||
| @mock.patch('importlib.import_module') | ||
| def test_compression_disabled(self, import_module): | ||
| async def test_compression_disabled(self, import_module): | ||
| a = self.get_async_mock( | ||
@@ -984,6 +981,6 @@ { | ||
| s.sockets['foo'] = mock_socket = self._get_mock_socket() | ||
| mock_socket.handle_get_request.mock.return_value = [ | ||
| mock_socket.handle_get_request.return_value = [ | ||
| packet.Packet(packet.MESSAGE, data='hello') | ||
| ] | ||
| _run(s.handle_request('request')) | ||
| await s.handle_request('request') | ||
| headers = a._async['make_response'].call_args[0][1] | ||
@@ -996,3 +993,3 @@ for header, value in headers: | ||
| @mock.patch('importlib.import_module') | ||
| def test_compression_unknown(self, import_module): | ||
| async def test_compression_unknown(self, import_module): | ||
| a = self.get_async_mock( | ||
@@ -1008,6 +1005,6 @@ { | ||
| s.sockets['foo'] = mock_socket = self._get_mock_socket() | ||
| mock_socket.handle_get_request.mock.return_value = [ | ||
| mock_socket.handle_get_request.return_value = [ | ||
| packet.Packet(packet.MESSAGE, data='hello') | ||
| ] | ||
| _run(s.handle_request('request')) | ||
| await s.handle_request('request') | ||
| headers = a._async['make_response'].call_args[0][1] | ||
@@ -1020,3 +1017,3 @@ for header, value in headers: | ||
| @mock.patch('importlib.import_module') | ||
| def test_compression_no_encoding(self, import_module): | ||
| async def test_compression_no_encoding(self, import_module): | ||
| a = self.get_async_mock( | ||
@@ -1032,6 +1029,6 @@ { | ||
| s.sockets['foo'] = mock_socket = self._get_mock_socket() | ||
| mock_socket.handle_get_request.mock.return_value = [ | ||
| mock_socket.handle_get_request.return_value = [ | ||
| packet.Packet(packet.MESSAGE, data='hello') | ||
| ] | ||
| _run(s.handle_request('request')) | ||
| await s.handle_request('request') | ||
| headers = a._async['make_response'].call_args[0][1] | ||
@@ -1044,3 +1041,3 @@ for header, value in headers: | ||
| @mock.patch('importlib.import_module') | ||
| def test_cookie(self, import_module): | ||
| async def test_cookie(self, import_module): | ||
| a = self.get_async_mock() | ||
@@ -1050,3 +1047,3 @@ import_module.side_effect = [a] | ||
| s.generate_id = mock.MagicMock(return_value='123') | ||
| _run(s.handle_request('request')) | ||
| await s.handle_request('request') | ||
| headers = a._async['make_response'].call_args[0][1] | ||
@@ -1056,3 +1053,3 @@ assert ('Set-Cookie', 'sid=123; path=/; SameSite=Lax') in headers | ||
| @mock.patch('importlib.import_module') | ||
| def test_cookie_dict(self, import_module): | ||
| async def test_cookie_dict(self, import_module): | ||
| def get_path(): | ||
@@ -1071,3 +1068,3 @@ return '/a' | ||
| s.generate_id = mock.MagicMock(return_value='123') | ||
| _run(s.handle_request('request')) | ||
| await s.handle_request('request') | ||
| headers = a._async['make_response'].call_args[0][1] | ||
@@ -1078,3 +1075,3 @@ assert ('Set-Cookie', 'test=123; path=/a; SameSite=None; Secure; ' | ||
| @mock.patch('importlib.import_module') | ||
| def test_no_cookie(self, import_module): | ||
| async def test_no_cookie(self, import_module): | ||
| a = self.get_async_mock() | ||
@@ -1084,3 +1081,3 @@ import_module.side_effect = [a] | ||
| s.generate_id = mock.MagicMock(return_value='123') | ||
| _run(s.handle_request('request')) | ||
| await s.handle_request('request') | ||
| headers = a._async['make_response'].call_args[0][1] | ||
@@ -1090,3 +1087,3 @@ for header, value in headers: | ||
| def test_logger(self): | ||
| async def test_logger(self): | ||
| s = async_server.AsyncServer(logger=False) | ||
@@ -1105,7 +1102,7 @@ assert s.logger.getEffectiveLevel() == logging.ERROR | ||
| def test_custom_json(self): | ||
| async def test_custom_json(self): | ||
| # Warning: this test cannot run in parallel with other tests, as it | ||
| # changes the JSON encoding/decoding functions | ||
| class CustomJSON(object): | ||
| class CustomJSON: | ||
| @staticmethod | ||
@@ -1128,3 +1125,3 @@ def dumps(*args, **kwargs): | ||
| def test_background_tasks(self): | ||
| async def test_background_tasks(self): | ||
| r = [] | ||
@@ -1135,14 +1132,15 @@ | ||
| s = async_server.AsyncServer() | ||
| s.start_background_task(foo, 'bar') | ||
| pending = asyncio.all_tasks(loop=asyncio.get_event_loop()) \ | ||
| if hasattr(asyncio, 'all_tasks') else asyncio.Task.all_tasks() | ||
| asyncio.get_event_loop().run_until_complete(asyncio.wait(pending)) | ||
| async def main(): | ||
| s = async_server.AsyncServer() | ||
| task = s.start_background_task(foo, 'bar') | ||
| await task | ||
| await main() | ||
| assert r == ['bar'] | ||
| def test_sleep(self): | ||
| async def test_sleep(self): | ||
| s = async_server.AsyncServer() | ||
| _run(s.sleep(0)) | ||
| await s.sleep(0) | ||
| def test_trigger_event_function(self): | ||
| async def test_trigger_event_function(self): | ||
| result = [] | ||
@@ -1156,6 +1154,6 @@ | ||
| s.on('message', handler=foo_handler) | ||
| _run(s._trigger_event('message', 'bar')) | ||
| await s._trigger_event('message', 'bar') | ||
| assert result == ['ok', 'bar'] | ||
| def test_trigger_event_coroutine(self): | ||
| async def test_trigger_event_coroutine(self): | ||
| result = [] | ||
@@ -1169,6 +1167,6 @@ | ||
| s.on('message', handler=foo_handler) | ||
| _run(s._trigger_event('message', 'bar')) | ||
| await s._trigger_event('message', 'bar') | ||
| assert result == ['ok', 'bar'] | ||
| def test_trigger_event_function_error(self): | ||
| async def test_trigger_event_function_error(self): | ||
| def connect_handler(arg): | ||
@@ -1183,6 +1181,6 @@ return 1 / 0 | ||
| s.on('message', handler=foo_handler) | ||
| assert not _run(s._trigger_event('connect', '123')) | ||
| assert _run(s._trigger_event('message', 'bar')) is None | ||
| assert not await s._trigger_event('connect', '123') | ||
| assert await s._trigger_event('message', 'bar') is None | ||
| def test_trigger_event_coroutine_error(self): | ||
| async def test_trigger_event_coroutine_error(self): | ||
| async def connect_handler(arg): | ||
@@ -1197,6 +1195,6 @@ return 1 / 0 | ||
| s.on('message', handler=foo_handler) | ||
| assert not _run(s._trigger_event('connect', '123')) | ||
| assert _run(s._trigger_event('message', 'bar')) is None | ||
| assert not await s._trigger_event('connect', '123') | ||
| assert await s._trigger_event('message', 'bar') is None | ||
| def test_trigger_event_function_async(self): | ||
| async def test_trigger_event_function_async(self): | ||
| result = [] | ||
@@ -1210,7 +1208,7 @@ | ||
| s.on('message', handler=foo_handler) | ||
| fut = _run(s._trigger_event('message', 'bar', run_async=True)) | ||
| asyncio.get_event_loop().run_until_complete(fut) | ||
| fut = await s._trigger_event('message', 'bar', run_async=True) | ||
| await fut | ||
| assert result == ['ok', 'bar'] | ||
| def test_trigger_event_coroutine_async(self): | ||
| async def test_trigger_event_coroutine_async(self): | ||
| result = [] | ||
@@ -1224,7 +1222,7 @@ | ||
| s.on('message', handler=foo_handler) | ||
| fut = _run(s._trigger_event('message', 'bar', run_async=True)) | ||
| asyncio.get_event_loop().run_until_complete(fut) | ||
| fut = await s._trigger_event('message', 'bar', run_async=True) | ||
| await fut | ||
| assert result == ['ok', 'bar'] | ||
| def test_trigger_event_function_async_error(self): | ||
| async def test_trigger_event_function_async_error(self): | ||
| result = [] | ||
@@ -1238,7 +1236,7 @@ | ||
| s.on('message', handler=foo_handler) | ||
| fut = _run(s._trigger_event('message', 'bar', run_async=True)) | ||
| asyncio.get_event_loop().run_until_complete(fut) | ||
| fut = await s._trigger_event('message', 'bar', run_async=True) | ||
| await fut | ||
| assert result == ['bar'] | ||
| def test_trigger_event_coroutine_async_error(self): | ||
| async def test_trigger_event_coroutine_async_error(self): | ||
| result = [] | ||
@@ -1252,8 +1250,28 @@ | ||
| s.on('message', handler=foo_handler) | ||
| fut = _run(s._trigger_event('message', 'bar', run_async=True)) | ||
| asyncio.get_event_loop().run_until_complete(fut) | ||
| fut = await s._trigger_event('message', 'bar', run_async=True) | ||
| await fut | ||
| assert result == ['bar'] | ||
| def test_create_queue(self): | ||
| async def test_trigger_legacy_disconnect_event(self): | ||
| s = async_server.AsyncServer() | ||
| @s.on('disconnect') | ||
| def baz(sid): | ||
| return sid | ||
| r = await s._trigger_event('disconnect', 'foo', 'bar') | ||
| assert r == 'foo' | ||
| async def test_trigger_legacy_disconnect_event_async(self): | ||
| s = async_server.AsyncServer() | ||
| @s.on('disconnect') | ||
| async def baz(sid): | ||
| return sid | ||
| r = await s._trigger_event('disconnect', 'foo', 'bar') | ||
| assert r == 'foo' | ||
| async def test_create_queue(self): | ||
| s = async_server.AsyncServer() | ||
| q = s.create_queue() | ||
@@ -1264,3 +1282,3 @@ empty = s.get_queue_empty_exception() | ||
| def test_create_event(self): | ||
| async def test_create_event(self): | ||
| s = async_server.AsyncServer() | ||
@@ -1273,22 +1291,24 @@ e = s.create_event() | ||
| @mock.patch('importlib.import_module') | ||
| def test_service_task_started(self, import_module): | ||
| async def test_service_task_started(self, import_module): | ||
| a = self.get_async_mock() | ||
| import_module.side_effect = [a] | ||
| s = async_server.AsyncServer(monitor_clients=True) | ||
| s._service_task = AsyncMock() | ||
| _run(s.handle_request('request')) | ||
| s._service_task.mock.assert_called_once_with() | ||
| s._service_task = mock.AsyncMock() | ||
| await s.handle_request('request') | ||
| await asyncio.sleep(0) | ||
| s._service_task.assert_awaited_once_with() | ||
| @mock.patch('importlib.import_module') | ||
| def test_shutdown(self, import_module): | ||
| async def test_shutdown(self, import_module): | ||
| a = self.get_async_mock() | ||
| import_module.side_effect = [a] | ||
| s = async_server.AsyncServer(monitor_clients=True) | ||
| _run(s.handle_request('request')) | ||
| await s.handle_request('request') | ||
| await asyncio.sleep(0) | ||
| assert s.service_task_handle is not None | ||
| _run(s.shutdown()) | ||
| await s.shutdown() | ||
| assert s.service_task_handle is None | ||
| @mock.patch('importlib.import_module') | ||
| def test_transports_disallowed(self, import_module): | ||
| async def test_transports_disallowed(self, import_module): | ||
| a = self.get_async_mock( | ||
@@ -1299,3 +1319,3 @@ {'REQUEST_METHOD': 'GET', 'QUERY_STRING': 'transport=polling'} | ||
| s = async_server.AsyncServer(transports='websocket') | ||
| response = _run(s.handle_request('request')) | ||
| response = await s.handle_request('request') | ||
| assert response == 'response' | ||
@@ -1302,0 +1322,0 @@ a._async['translate_request'].assert_called_once_with('request') |
+184
-194
| import asyncio | ||
| import time | ||
| import unittest | ||
| from unittest import mock | ||
@@ -14,23 +13,7 @@ | ||
| def AsyncMock(*args, **kwargs): | ||
| """Return a mock asynchronous function.""" | ||
| m = mock.MagicMock(*args, **kwargs) | ||
| async def mock_coro(*args, **kwargs): | ||
| return m(*args, **kwargs) | ||
| mock_coro.mock = m | ||
| return mock_coro | ||
| def _run(coro): | ||
| """Run the given coroutine.""" | ||
| return asyncio.get_event_loop().run_until_complete(coro) | ||
| class TestSocket(unittest.TestCase): | ||
| class TestSocket: | ||
| def _get_read_mock_coro(self, payload): | ||
| mock_input = mock.MagicMock() | ||
| mock_input.read = AsyncMock() | ||
| mock_input.read.mock.return_value = payload | ||
| mock_input.read = mock.AsyncMock() | ||
| mock_input.read.return_value = payload | ||
| return mock_input | ||
@@ -54,3 +37,3 @@ | ||
| mock_server._async['make_response'].return_value = 'response' | ||
| mock_server._trigger_event = AsyncMock() | ||
| mock_server._trigger_event = mock.AsyncMock() | ||
@@ -69,3 +52,3 @@ def bg_task(target, *args, **kwargs): | ||
| def test_create(self): | ||
| async def test_create(self): | ||
| mock_server = self._get_mock_server() | ||
@@ -82,9 +65,9 @@ s = async_socket.AsyncSocket(mock_server, 'sid') | ||
| def test_empty_poll(self): | ||
| async def test_empty_poll(self): | ||
| mock_server = self._get_mock_server() | ||
| s = async_socket.AsyncSocket(mock_server, 'sid') | ||
| with pytest.raises(exceptions.QueueEmpty): | ||
| _run(s.poll()) | ||
| await s.poll() | ||
| def test_poll(self): | ||
| async def test_poll(self): | ||
| mock_server = self._get_mock_server() | ||
@@ -94,26 +77,26 @@ s = async_socket.AsyncSocket(mock_server, 'sid') | ||
| pkt2 = packet.Packet(packet.MESSAGE, data='bye') | ||
| _run(s.send(pkt1)) | ||
| _run(s.send(pkt2)) | ||
| assert _run(s.poll()) == [pkt1, pkt2] | ||
| await s.send(pkt1) | ||
| await s.send(pkt2) | ||
| assert await s.poll() == [pkt1, pkt2] | ||
| def test_poll_none(self): | ||
| async def test_poll_none(self): | ||
| mock_server = self._get_mock_server() | ||
| s = async_socket.AsyncSocket(mock_server, 'sid') | ||
| _run(s.queue.put(None)) | ||
| assert _run(s.poll()) == [] | ||
| await s.queue.put(None) | ||
| assert await s.poll() == [] | ||
| def test_poll_none_after_packet(self): | ||
| async def test_poll_none_after_packet(self): | ||
| mock_server = self._get_mock_server() | ||
| s = async_socket.AsyncSocket(mock_server, 'sid') | ||
| pkt = packet.Packet(packet.MESSAGE, data='hello') | ||
| _run(s.send(pkt)) | ||
| _run(s.queue.put(None)) | ||
| assert _run(s.poll()) == [pkt] | ||
| assert _run(s.poll()) == [] | ||
| await s.send(pkt) | ||
| await s.queue.put(None) | ||
| assert await s.poll() == [pkt] | ||
| assert await s.poll() == [] | ||
| def test_schedule_ping(self): | ||
| async def test_schedule_ping(self): | ||
| mock_server = self._get_mock_server() | ||
| mock_server.ping_interval = 0.01 | ||
| s = async_socket.AsyncSocket(mock_server, 'sid') | ||
| s.send = AsyncMock() | ||
| s.send = mock.AsyncMock() | ||
@@ -124,11 +107,11 @@ async def schedule_ping(): | ||
| _run(schedule_ping()) | ||
| await schedule_ping() | ||
| assert s.last_ping is not None | ||
| assert s.send.mock.call_args_list[0][0][0].encode() == '2' | ||
| assert s.send.await_args_list[0][0][0].encode() == '2' | ||
| def test_schedule_ping_closed_socket(self): | ||
| async def test_schedule_ping_closed_socket(self): | ||
| mock_server = self._get_mock_server() | ||
| mock_server.ping_interval = 0.01 | ||
| s = async_socket.AsyncSocket(mock_server, 'sid') | ||
| s.send = AsyncMock() | ||
| s.send = mock.AsyncMock() | ||
| s.closed = True | ||
@@ -140,37 +123,37 @@ | ||
| _run(schedule_ping()) | ||
| await schedule_ping() | ||
| assert s.last_ping is None | ||
| s.send.mock.assert_not_called() | ||
| s.send.assert_not_awaited() | ||
| def test_pong(self): | ||
| async def test_pong(self): | ||
| mock_server = self._get_mock_server() | ||
| s = async_socket.AsyncSocket(mock_server, 'sid') | ||
| s.schedule_ping = mock.MagicMock() | ||
| _run(s.receive(packet.Packet(packet.PONG, data='abc'))) | ||
| await s.receive(packet.Packet(packet.PONG, data='abc')) | ||
| s.schedule_ping.assert_called_once_with() | ||
| def test_message_sync_handler(self): | ||
| async def test_message_sync_handler(self): | ||
| mock_server = self._get_mock_server() | ||
| s = async_socket.AsyncSocket(mock_server, 'sid') | ||
| _run(s.receive(packet.Packet(packet.MESSAGE, data='foo'))) | ||
| mock_server._trigger_event.mock.assert_called_once_with( | ||
| await s.receive(packet.Packet(packet.MESSAGE, data='foo')) | ||
| mock_server._trigger_event.assert_awaited_once_with( | ||
| 'message', 'sid', 'foo', run_async=False | ||
| ) | ||
| def test_message_async_handler(self): | ||
| async def test_message_async_handler(self): | ||
| mock_server = self._get_mock_server() | ||
| s = async_socket.AsyncSocket(mock_server, 'sid') | ||
| mock_server.async_handlers = True | ||
| _run(s.receive(packet.Packet(packet.MESSAGE, data='foo'))) | ||
| mock_server._trigger_event.mock.assert_called_once_with( | ||
| await s.receive(packet.Packet(packet.MESSAGE, data='foo')) | ||
| mock_server._trigger_event.assert_awaited_once_with( | ||
| 'message', 'sid', 'foo', run_async=True | ||
| ) | ||
| def test_invalid_packet(self): | ||
| async def test_invalid_packet(self): | ||
| mock_server = self._get_mock_server() | ||
| s = async_socket.AsyncSocket(mock_server, 'sid') | ||
| with pytest.raises(exceptions.UnknownPacketError): | ||
| _run(s.receive(packet.Packet(packet.OPEN))) | ||
| await s.receive(packet.Packet(packet.OPEN)) | ||
| def test_timeout(self): | ||
| async def test_timeout(self): | ||
| mock_server = self._get_mock_server() | ||
@@ -181,7 +164,8 @@ mock_server.ping_interval = 6 | ||
| s.last_ping = time.time() - 9 | ||
| s.close = AsyncMock() | ||
| _run(s.send('packet')) | ||
| s.close.mock.assert_called_once_with(wait=False, abort=False) | ||
| s.close = mock.AsyncMock() | ||
| await s.send('packet') | ||
| s.close.assert_awaited_once_with( | ||
| wait=False, abort=False, reason=mock_server.reason.PING_TIMEOUT) | ||
| def test_polling_read(self): | ||
| async def test_polling_read(self): | ||
| mock_server = self._get_mock_server() | ||
@@ -191,9 +175,9 @@ s = async_socket.AsyncSocket(mock_server, 'foo') | ||
| pkt2 = packet.Packet(packet.MESSAGE, data='bye') | ||
| _run(s.send(pkt1)) | ||
| _run(s.send(pkt2)) | ||
| await s.send(pkt1) | ||
| await s.send(pkt2) | ||
| environ = {'REQUEST_METHOD': 'GET', 'QUERY_STRING': 'sid=foo'} | ||
| packets = _run(s.handle_get_request(environ)) | ||
| packets = await s.handle_get_request(environ) | ||
| assert packets == [pkt1, pkt2] | ||
| def test_polling_read_error(self): | ||
| async def test_polling_read_error(self): | ||
| mock_server = self._get_mock_server() | ||
@@ -203,5 +187,5 @@ s = async_socket.AsyncSocket(mock_server, 'foo') | ||
| with pytest.raises(exceptions.QueueEmpty): | ||
| _run(s.handle_get_request(environ)) | ||
| await s.handle_get_request(environ) | ||
| def test_polling_write(self): | ||
| async def test_polling_write(self): | ||
| mock_server = self._get_mock_server() | ||
@@ -213,3 +197,3 @@ mock_server.max_http_buffer_size = 1000 | ||
| s = async_socket.AsyncSocket(mock_server, 'foo') | ||
| s.receive = AsyncMock() | ||
| s.receive = mock.AsyncMock() | ||
| environ = { | ||
@@ -221,6 +205,6 @@ 'REQUEST_METHOD': 'POST', | ||
| } | ||
| _run(s.handle_post_request(environ)) | ||
| assert s.receive.mock.call_count == 2 | ||
| await s.handle_post_request(environ) | ||
| assert s.receive.await_count == 2 | ||
| def test_polling_write_too_large(self): | ||
| async def test_polling_write_too_large(self): | ||
| mock_server = self._get_mock_server() | ||
@@ -232,3 +216,3 @@ pkt1 = packet.Packet(packet.MESSAGE, data='hello') | ||
| s = async_socket.AsyncSocket(mock_server, 'foo') | ||
| s.receive = AsyncMock() | ||
| s.receive = mock.AsyncMock() | ||
| environ = { | ||
@@ -241,8 +225,8 @@ 'REQUEST_METHOD': 'POST', | ||
| with pytest.raises(exceptions.ContentTooLongError): | ||
| _run(s.handle_post_request(environ)) | ||
| await s.handle_post_request(environ) | ||
| def test_upgrade_handshake(self): | ||
| async def test_upgrade_handshake(self): | ||
| mock_server = self._get_mock_server() | ||
| s = async_socket.AsyncSocket(mock_server, 'foo') | ||
| s._upgrade_websocket = AsyncMock() | ||
| s._upgrade_websocket = mock.AsyncMock() | ||
| environ = { | ||
@@ -254,9 +238,9 @@ 'REQUEST_METHOD': 'GET', | ||
| } | ||
| _run(s.handle_get_request(environ)) | ||
| s._upgrade_websocket.mock.assert_called_once_with(environ) | ||
| await s.handle_get_request(environ) | ||
| s._upgrade_websocket.assert_awaited_once_with(environ) | ||
| def test_upgrade(self): | ||
| async def test_upgrade(self): | ||
| mock_server = self._get_mock_server() | ||
| mock_server._async['websocket'] = mock.MagicMock() | ||
| mock_ws = AsyncMock() | ||
| mock_ws = mock.AsyncMock() | ||
| mock_server._async['websocket'].return_value = mock_ws | ||
@@ -266,9 +250,9 @@ s = async_socket.AsyncSocket(mock_server, 'sid') | ||
| environ = "foo" | ||
| _run(s._upgrade_websocket(environ)) | ||
| await s._upgrade_websocket(environ) | ||
| mock_server._async['websocket'].assert_called_once_with( | ||
| s._websocket_handler, mock_server | ||
| ) | ||
| mock_ws.mock.assert_called_once_with(environ) | ||
| mock_ws.assert_awaited_once_with(environ) | ||
| def test_upgrade_twice(self): | ||
| async def test_upgrade_twice(self): | ||
| mock_server = self._get_mock_server() | ||
@@ -281,14 +265,14 @@ mock_server._async['websocket'] = mock.MagicMock() | ||
| with pytest.raises(IOError): | ||
| _run(s._upgrade_websocket(environ)) | ||
| await s._upgrade_websocket(environ) | ||
| def test_upgrade_packet(self): | ||
| async def test_upgrade_packet(self): | ||
| mock_server = self._get_mock_server() | ||
| s = async_socket.AsyncSocket(mock_server, 'sid') | ||
| s.connected = True | ||
| _run(s.receive(packet.Packet(packet.UPGRADE))) | ||
| r = _run(s.poll()) | ||
| await s.receive(packet.Packet(packet.UPGRADE)) | ||
| r = await s.poll() | ||
| assert len(r) == 1 | ||
| assert r[0].encode() == packet.Packet(packet.NOOP).encode() | ||
| def test_upgrade_no_probe(self): | ||
| async def test_upgrade_no_probe(self): | ||
| mock_server = self._get_mock_server() | ||
@@ -298,28 +282,28 @@ s = async_socket.AsyncSocket(mock_server, 'sid') | ||
| ws = mock.MagicMock() | ||
| ws.wait = AsyncMock() | ||
| ws.wait.mock.return_value = packet.Packet(packet.NOOP).encode() | ||
| _run(s._websocket_handler(ws)) | ||
| ws.wait = mock.AsyncMock() | ||
| ws.wait.return_value = packet.Packet(packet.NOOP).encode() | ||
| await s._websocket_handler(ws) | ||
| assert not s.upgraded | ||
| def test_upgrade_no_upgrade_packet(self): | ||
| async def test_upgrade_no_upgrade_packet(self): | ||
| mock_server = self._get_mock_server() | ||
| s = async_socket.AsyncSocket(mock_server, 'sid') | ||
| s.connected = True | ||
| s.queue.join = AsyncMock(return_value=None) | ||
| s.queue.join = mock.AsyncMock(return_value=None) | ||
| ws = mock.MagicMock() | ||
| ws.send = AsyncMock() | ||
| ws.wait = AsyncMock() | ||
| ws.send = mock.AsyncMock() | ||
| ws.wait = mock.AsyncMock() | ||
| probe = 'probe' | ||
| ws.wait.mock.side_effect = [ | ||
| ws.wait.side_effect = [ | ||
| packet.Packet(packet.PING, data=probe).encode(), | ||
| packet.Packet(packet.NOOP).encode(), | ||
| ] | ||
| _run(s._websocket_handler(ws)) | ||
| ws.send.mock.assert_called_once_with( | ||
| await s._websocket_handler(ws) | ||
| ws.send.assert_awaited_once_with( | ||
| packet.Packet(packet.PONG, data=probe).encode() | ||
| ) | ||
| assert _run(s.queue.get()).packet_type == packet.NOOP | ||
| assert (await s.queue.get()).packet_type == packet.NOOP | ||
| assert not s.upgraded | ||
| def test_upgrade_not_supported(self): | ||
| async def test_upgrade_not_supported(self): | ||
| mock_server = self._get_mock_server() | ||
@@ -330,53 +314,56 @@ mock_server._async['websocket'] = None | ||
| environ = "foo" | ||
| _run(s._upgrade_websocket(environ)) | ||
| await s._upgrade_websocket(environ) | ||
| mock_server._bad_request.assert_called_once_with() | ||
| def test_close_packet(self): | ||
| async def test_close_packet(self): | ||
| mock_server = self._get_mock_server() | ||
| s = async_socket.AsyncSocket(mock_server, 'sid') | ||
| s.connected = True | ||
| s.close = AsyncMock() | ||
| _run(s.receive(packet.Packet(packet.CLOSE))) | ||
| s.close.mock.assert_called_once_with(wait=False, abort=True) | ||
| s.close = mock.AsyncMock() | ||
| await s.receive(packet.Packet(packet.CLOSE)) | ||
| s.close.assert_awaited_once_with( | ||
| wait=False, abort=True, | ||
| reason=mock_server.reason.CLIENT_DISCONNECT) | ||
| def test_websocket_read_write(self): | ||
| async def test_websocket_read_write(self): | ||
| mock_server = self._get_mock_server() | ||
| s = async_socket.AsyncSocket(mock_server, 'sid') | ||
| s.connected = False | ||
| s.queue.join = AsyncMock(return_value=None) | ||
| s.queue.join = mock.AsyncMock(return_value=None) | ||
| foo = 'foo' | ||
| bar = 'bar' | ||
| s.poll = AsyncMock( | ||
| s.poll = mock.AsyncMock( | ||
| side_effect=[[packet.Packet(packet.MESSAGE, data=bar)], None] | ||
| ) | ||
| ws = mock.MagicMock() | ||
| ws.send = AsyncMock() | ||
| ws.wait = AsyncMock() | ||
| ws.wait.mock.side_effect = [ | ||
| ws.send = mock.AsyncMock() | ||
| ws.wait = mock.AsyncMock() | ||
| ws.wait.side_effect = [ | ||
| packet.Packet(packet.MESSAGE, data=foo).encode(), | ||
| None, | ||
| ] | ||
| ws.close = AsyncMock() | ||
| _run(s._websocket_handler(ws)) | ||
| ws.close = mock.AsyncMock() | ||
| await s._websocket_handler(ws) | ||
| assert s.connected | ||
| assert s.upgraded | ||
| assert mock_server._trigger_event.mock.call_count == 2 | ||
| mock_server._trigger_event.mock.assert_has_calls( | ||
| assert mock_server._trigger_event.await_count == 2 | ||
| mock_server._trigger_event.assert_has_awaits( | ||
| [ | ||
| mock.call('message', 'sid', 'foo', run_async=False), | ||
| mock.call('disconnect', 'sid'), | ||
| mock.call('disconnect', 'sid', | ||
| mock_server.reason.TRANSPORT_CLOSE, run_async=False), | ||
| ] | ||
| ) | ||
| ws.send.mock.assert_called_with('4bar') | ||
| ws.close.mock.assert_called() | ||
| ws.send.assert_awaited_with('4bar') | ||
| ws.close.assert_awaited() | ||
| def test_websocket_upgrade_read_write(self): | ||
| async def test_websocket_upgrade_read_write(self): | ||
| mock_server = self._get_mock_server() | ||
| s = async_socket.AsyncSocket(mock_server, 'sid') | ||
| s.connected = True | ||
| s.queue.join = AsyncMock(return_value=None) | ||
| s.queue.join = mock.AsyncMock(return_value=None) | ||
| foo = 'foo' | ||
| bar = 'bar' | ||
| probe = 'probe' | ||
| s.poll = AsyncMock( | ||
| s.poll = mock.AsyncMock( | ||
| side_effect=[ | ||
@@ -388,5 +375,5 @@ [packet.Packet(packet.MESSAGE, data=bar)], | ||
| ws = mock.MagicMock() | ||
| ws.send = AsyncMock() | ||
| ws.wait = AsyncMock() | ||
| ws.wait.mock.side_effect = [ | ||
| ws.send = mock.AsyncMock() | ||
| ws.wait = mock.AsyncMock() | ||
| ws.wait.side_effect = [ | ||
| packet.Packet(packet.PING, data=probe).encode(), | ||
@@ -397,72 +384,73 @@ packet.Packet(packet.UPGRADE).encode(), | ||
| ] | ||
| ws.close = AsyncMock() | ||
| _run(s._websocket_handler(ws)) | ||
| ws.close = mock.AsyncMock() | ||
| await s._websocket_handler(ws) | ||
| assert s.upgraded | ||
| assert mock_server._trigger_event.mock.call_count == 2 | ||
| mock_server._trigger_event.mock.assert_has_calls( | ||
| assert mock_server._trigger_event.await_count == 2 | ||
| mock_server._trigger_event.assert_has_awaits( | ||
| [ | ||
| mock.call('message', 'sid', 'foo', run_async=False), | ||
| mock.call('disconnect', 'sid'), | ||
| mock.call('disconnect', 'sid', | ||
| mock_server.reason.TRANSPORT_CLOSE, run_async=False), | ||
| ] | ||
| ) | ||
| ws.send.mock.assert_called_with('4bar') | ||
| ws.close.mock.assert_called() | ||
| ws.send.assert_awaited_with('4bar') | ||
| ws.close.assert_awaited() | ||
| def test_websocket_upgrade_with_payload(self): | ||
| async def test_websocket_upgrade_with_payload(self): | ||
| mock_server = self._get_mock_server() | ||
| s = async_socket.AsyncSocket(mock_server, 'sid') | ||
| s.connected = True | ||
| s.queue.join = AsyncMock(return_value=None) | ||
| s.queue.join = mock.AsyncMock(return_value=None) | ||
| probe = 'probe' | ||
| ws = mock.MagicMock() | ||
| ws.send = AsyncMock() | ||
| ws.wait = AsyncMock() | ||
| ws.wait.mock.side_effect = [ | ||
| ws.send = mock.AsyncMock() | ||
| ws.wait = mock.AsyncMock() | ||
| ws.wait.side_effect = [ | ||
| packet.Packet(packet.PING, data=probe).encode(), | ||
| packet.Packet(packet.UPGRADE, data='2').encode(), | ||
| ] | ||
| ws.close = AsyncMock() | ||
| _run(s._websocket_handler(ws)) | ||
| ws.close = mock.AsyncMock() | ||
| await s._websocket_handler(ws) | ||
| assert s.upgraded | ||
| def test_websocket_upgrade_with_backlog(self): | ||
| async def test_websocket_upgrade_with_backlog(self): | ||
| mock_server = self._get_mock_server() | ||
| s = async_socket.AsyncSocket(mock_server, 'sid') | ||
| s.connected = True | ||
| s.queue.join = AsyncMock(return_value=None) | ||
| s.queue.join = mock.AsyncMock(return_value=None) | ||
| probe = 'probe' | ||
| foo = 'foo' | ||
| ws = mock.MagicMock() | ||
| ws.send = AsyncMock() | ||
| ws.wait = AsyncMock() | ||
| ws.wait.mock.side_effect = [ | ||
| ws.send = mock.AsyncMock() | ||
| ws.wait = mock.AsyncMock() | ||
| ws.wait.side_effect = [ | ||
| packet.Packet(packet.PING, data=probe).encode(), | ||
| packet.Packet(packet.UPGRADE, data='2').encode(), | ||
| ] | ||
| ws.close = AsyncMock() | ||
| ws.close = mock.AsyncMock() | ||
| s.upgrading = True | ||
| _run(s.send(packet.Packet(packet.MESSAGE, data=foo))) | ||
| await s.send(packet.Packet(packet.MESSAGE, data=foo)) | ||
| environ = {'REQUEST_METHOD': 'GET', 'QUERY_STRING': 'sid=sid'} | ||
| packets = _run(s.handle_get_request(environ)) | ||
| packets = await s.handle_get_request(environ) | ||
| assert len(packets) == 1 | ||
| assert packets[0].encode() == '6' | ||
| packets = _run(s.poll()) | ||
| packets = await s.poll() | ||
| assert len(packets) == 1 | ||
| assert packets[0].encode() == '4foo' | ||
| _run(s._websocket_handler(ws)) | ||
| await s._websocket_handler(ws) | ||
| assert s.upgraded | ||
| assert not s.upgrading | ||
| packets = _run(s.handle_get_request(environ)) | ||
| packets = await s.handle_get_request(environ) | ||
| assert len(packets) == 1 | ||
| assert packets[0].encode() == '6' | ||
| def test_websocket_read_write_wait_fail(self): | ||
| async def test_websocket_read_write_wait_fail(self): | ||
| mock_server = self._get_mock_server() | ||
| s = async_socket.AsyncSocket(mock_server, 'sid') | ||
| s.connected = False | ||
| s.queue.join = AsyncMock(return_value=None) | ||
| s.queue.join = mock.AsyncMock(return_value=None) | ||
| foo = 'foo' | ||
| bar = 'bar' | ||
| s.poll = AsyncMock( | ||
| s.poll = mock.AsyncMock( | ||
| side_effect=[ | ||
@@ -475,23 +463,23 @@ [packet.Packet(packet.MESSAGE, data=bar)], | ||
| ws = mock.MagicMock() | ||
| ws.send = AsyncMock() | ||
| ws.wait = AsyncMock() | ||
| ws.wait.mock.side_effect = [ | ||
| ws.send = mock.AsyncMock() | ||
| ws.wait = mock.AsyncMock() | ||
| ws.wait.side_effect = [ | ||
| packet.Packet(packet.MESSAGE, data=foo).encode(), | ||
| RuntimeError, | ||
| ] | ||
| ws.send.mock.side_effect = [None, RuntimeError] | ||
| ws.close = AsyncMock() | ||
| _run(s._websocket_handler(ws)) | ||
| ws.send.side_effect = [None, RuntimeError] | ||
| ws.close = mock.AsyncMock() | ||
| await s._websocket_handler(ws) | ||
| assert s.closed | ||
| def test_websocket_upgrade_with_large_packet(self): | ||
| async def test_websocket_upgrade_with_large_packet(self): | ||
| mock_server = self._get_mock_server() | ||
| s = async_socket.AsyncSocket(mock_server, 'sid') | ||
| s.connected = True | ||
| s.queue.join = AsyncMock(return_value=None) | ||
| s.queue.join = mock.AsyncMock(return_value=None) | ||
| probe = 'probe' | ||
| ws = mock.MagicMock() | ||
| ws.send = AsyncMock() | ||
| ws.wait = AsyncMock() | ||
| ws.wait.mock.side_effect = [ | ||
| ws.send = mock.AsyncMock() | ||
| ws.wait = mock.AsyncMock() | ||
| ws.wait.side_effect = [ | ||
| packet.Packet(packet.PING, data=probe).encode(), | ||
@@ -501,13 +489,13 @@ packet.Packet(packet.UPGRADE, data='2' * 128).encode(), | ||
| with pytest.raises(ValueError): | ||
| _run(s._websocket_handler(ws)) | ||
| await s._websocket_handler(ws) | ||
| assert not s.upgraded | ||
| def test_websocket_ignore_invalid_packet(self): | ||
| async def test_websocket_ignore_invalid_packet(self): | ||
| mock_server = self._get_mock_server() | ||
| s = async_socket.AsyncSocket(mock_server, 'sid') | ||
| s.connected = False | ||
| s.queue.join = AsyncMock(return_value=None) | ||
| s.queue.join = mock.AsyncMock(return_value=None) | ||
| foo = 'foo' | ||
| bar = 'bar' | ||
| s.poll = AsyncMock( | ||
| s.poll = mock.AsyncMock( | ||
| side_effect=[ | ||
@@ -519,5 +507,5 @@ [packet.Packet(packet.MESSAGE, data=bar)], | ||
| ws = mock.MagicMock() | ||
| ws.send = AsyncMock() | ||
| ws.wait = AsyncMock() | ||
| ws.wait.mock.side_effect = [ | ||
| ws.send = mock.AsyncMock() | ||
| ws.wait = mock.AsyncMock() | ||
| ws.wait.side_effect = [ | ||
| packet.Packet(packet.OPEN).encode(), | ||
@@ -527,50 +515,52 @@ packet.Packet(packet.MESSAGE, data=foo).encode(), | ||
| ] | ||
| ws.close = AsyncMock() | ||
| _run(s._websocket_handler(ws)) | ||
| ws.close = mock.AsyncMock() | ||
| await s._websocket_handler(ws) | ||
| assert s.connected | ||
| assert mock_server._trigger_event.mock.call_count == 2 | ||
| mock_server._trigger_event.mock.assert_has_calls( | ||
| assert mock_server._trigger_event.await_count == 2 | ||
| mock_server._trigger_event.assert_has_awaits( | ||
| [ | ||
| mock.call('message', 'sid', foo, run_async=False), | ||
| mock.call('disconnect', 'sid'), | ||
| mock.call('disconnect', 'sid', | ||
| mock_server.reason.TRANSPORT_CLOSE, run_async=False), | ||
| ] | ||
| ) | ||
| ws.send.mock.assert_called_with('4bar') | ||
| ws.close.mock.assert_called() | ||
| ws.send.assert_awaited_with('4bar') | ||
| ws.close.assert_awaited() | ||
| def test_send_after_close(self): | ||
| async def test_send_after_close(self): | ||
| mock_server = self._get_mock_server() | ||
| s = async_socket.AsyncSocket(mock_server, 'sid') | ||
| _run(s.close(wait=False)) | ||
| await s.close(wait=False) | ||
| with pytest.raises(exceptions.SocketIsClosedError): | ||
| _run(s.send(packet.Packet(packet.NOOP))) | ||
| await s.send(packet.Packet(packet.NOOP)) | ||
| def test_close_after_close(self): | ||
| async def test_close_after_close(self): | ||
| mock_server = self._get_mock_server() | ||
| s = async_socket.AsyncSocket(mock_server, 'sid') | ||
| _run(s.close(wait=False)) | ||
| await s.close(wait=False) | ||
| assert s.closed | ||
| assert mock_server._trigger_event.mock.call_count == 1 | ||
| mock_server._trigger_event.mock.assert_called_once_with( | ||
| 'disconnect', 'sid' | ||
| assert mock_server._trigger_event.await_count == 1 | ||
| mock_server._trigger_event.assert_awaited_once_with( | ||
| 'disconnect', 'sid', mock_server.reason.SERVER_DISCONNECT, | ||
| run_async=False | ||
| ) | ||
| _run(s.close()) | ||
| assert mock_server._trigger_event.mock.call_count == 1 | ||
| await s.close() | ||
| assert mock_server._trigger_event.await_count == 1 | ||
| def test_close_and_wait(self): | ||
| async def test_close_and_wait(self): | ||
| mock_server = self._get_mock_server() | ||
| s = async_socket.AsyncSocket(mock_server, 'sid') | ||
| s.queue = mock.MagicMock() | ||
| s.queue.put = AsyncMock() | ||
| s.queue.join = AsyncMock() | ||
| _run(s.close(wait=True)) | ||
| s.queue.join.mock.assert_called_once_with() | ||
| s.queue.put = mock.AsyncMock() | ||
| s.queue.join = mock.AsyncMock() | ||
| await s.close(wait=True) | ||
| s.queue.join.assert_awaited_once_with() | ||
| def test_close_without_wait(self): | ||
| async def test_close_without_wait(self): | ||
| mock_server = self._get_mock_server() | ||
| s = async_socket.AsyncSocket(mock_server, 'sid') | ||
| s.queue = mock.MagicMock() | ||
| s.queue.put = AsyncMock() | ||
| s.queue.join = AsyncMock() | ||
| _run(s.close(wait=False)) | ||
| assert s.queue.join.mock.call_count == 0 | ||
| s.queue.put = mock.AsyncMock() | ||
| s.queue.join = mock.AsyncMock() | ||
| await s.close(wait=False) | ||
| assert s.queue.join.await_count == 0 |
@@ -1,3 +0,1 @@ | ||
| import asyncio | ||
| import unittest | ||
| from unittest import mock | ||
@@ -13,9 +11,4 @@ | ||
| def _run(coro): | ||
| """Run the given coroutine.""" | ||
| return asyncio.get_event_loop().run_until_complete(coro) | ||
| class TornadoTests(unittest.TestCase): | ||
| def test_get_tornado_handler(self): | ||
| class TestTornado: | ||
| async def test_get_tornado_handler(self): | ||
| mock_server = mock.MagicMock() | ||
@@ -25,3 +18,3 @@ handler = async_tornado.get_tornado_handler(mock_server) | ||
| def test_translate_request(self): | ||
| async def test_translate_request(self): | ||
| mock_handler = mock.MagicMock() | ||
@@ -55,7 +48,7 @@ mock_handler.request.method = 'PUT' | ||
| assert v == environ[k] | ||
| payload = _run(environ['wsgi.input'].read(1)) | ||
| payload += _run(environ['wsgi.input'].read()) | ||
| payload = await environ['wsgi.input'].read(1) | ||
| payload += await environ['wsgi.input'].read() | ||
| assert payload == b'hello world' | ||
| def test_make_response(self): | ||
| async def test_make_response(self): | ||
| mock_handler = mock.MagicMock() | ||
@@ -62,0 +55,0 @@ mock_environ = {'tornado.handler': mock_handler} |
| import logging | ||
| import ssl | ||
| import time | ||
| import unittest | ||
| from unittest import mock | ||
@@ -18,3 +17,3 @@ | ||
| class TestClient(unittest.TestCase): | ||
| class TestClient: | ||
| def test_is_asyncio_based(self): | ||
@@ -43,3 +42,3 @@ c = client.Client() | ||
| def test_custon_json(self): | ||
| def test_custom_json(self): | ||
| client.Client() | ||
@@ -71,2 +70,10 @@ assert packet.Packet.json == json | ||
| def test_timestamp_requests(self): | ||
| c = client.Client() | ||
| assert c.timestamp_requests | ||
| assert c._get_url_timestamp().startswith('&t=') | ||
| c = client.Client(timestamp_requests=False) | ||
| assert not c.timestamp_requests | ||
| assert c._get_url_timestamp() == '' | ||
| def test_on_event(self): | ||
@@ -215,3 +222,4 @@ c = client.Client() | ||
| assert c not in base_client.connected_clients | ||
| c._trigger_event.assert_called_once_with('disconnect', run_async=False) | ||
| c._trigger_event.assert_called_once_with( | ||
| 'disconnect', c.reason.CLIENT_DISCONNECT, run_async=False) | ||
@@ -231,3 +239,4 @@ def test_disconnect_websocket(self): | ||
| assert c not in base_client.connected_clients | ||
| c._trigger_event.assert_called_once_with('disconnect', run_async=False) | ||
| c._trigger_event.assert_called_once_with( | ||
| 'disconnect', c.reason.CLIENT_DISCONNECT, run_async=False) | ||
@@ -1201,3 +1210,4 @@ def test_disconnect_polling_abort(self): | ||
| c._receive_packet(packet.Packet(packet.CLOSE)) | ||
| c.disconnect.assert_called_once_with(abort=True) | ||
| c.disconnect.assert_called_once_with( | ||
| abort=True, reason=c.reason.SERVER_DISCONNECT) | ||
@@ -1233,2 +1243,6 @@ def test_send_packet_disconnected(self): | ||
| @c.on('disconnect') | ||
| def baz(reason): | ||
| return reason | ||
| r = c._trigger_event('connect', run_async=False) | ||
@@ -1241,3 +1255,15 @@ assert r == 'foo' | ||
| assert r == 'bar' | ||
| r = c._trigger_event('disconnect', 'foo') | ||
| assert r == 'foo' | ||
| def test_trigger_legacy_disconnect_event(self): | ||
| c = client.Client() | ||
| @c.on('disconnect') | ||
| def baz(): | ||
| return 'baz' | ||
| r = c._trigger_event('disconnect', 'foo') | ||
| assert r == 'baz' | ||
| def test_trigger_unknown_event(self): | ||
@@ -1327,3 +1353,4 @@ c = client.Client() | ||
| ) | ||
| c._trigger_event.assert_called_once_with('disconnect', run_async=False) | ||
| c._trigger_event.assert_called_once_with( | ||
| 'disconnect', c.reason.TRANSPORT_ERROR, run_async=False) | ||
@@ -1330,0 +1357,0 @@ @mock.patch('engineio.client.time.time', return_value=123.456) |
| import os | ||
| import unittest | ||
| from unittest import mock | ||
@@ -8,3 +7,3 @@ | ||
| class TestWSGIApp(unittest.TestCase): | ||
| class TestWSGIApp: | ||
| def test_wsgi_routing(self): | ||
@@ -11,0 +10,0 @@ mock_wsgi_app = mock.MagicMock() |
@@ -1,3 +0,1 @@ | ||
| import unittest | ||
| import pytest | ||
@@ -8,3 +6,3 @@ | ||
| class TestPacket(unittest.TestCase): | ||
| class TestPacket: | ||
| def test_encode_default_packet(self): | ||
@@ -11,0 +9,0 @@ pkt = packet.Packet() |
@@ -1,3 +0,1 @@ | ||
| import unittest | ||
| import pytest | ||
@@ -9,3 +7,3 @@ | ||
| class TestPayload(unittest.TestCase): | ||
| class TestPayload: | ||
| def test_encode_empty_payload(self): | ||
@@ -12,0 +10,0 @@ p = payload.Payload() |
@@ -7,3 +7,2 @@ import gzip | ||
| import time | ||
| import unittest | ||
| from unittest import mock | ||
@@ -29,3 +28,3 @@ import zlib | ||
| class TestServer(unittest.TestCase): | ||
| class TestServer: | ||
| _mock_async = mock.MagicMock() | ||
@@ -48,13 +47,13 @@ _mock_async._async = { | ||
| @classmethod | ||
| def setUpClass(cls): | ||
| def setup_class(cls): | ||
| server.Server._default_monitor_clients = False | ||
| @classmethod | ||
| def tearDownClass(cls): | ||
| def teardown_class(cls): | ||
| server.Server._default_monitor_clients = True | ||
| def setUp(self): | ||
| def setup_method(self): | ||
| logging.getLogger('engineio').setLevel(logging.NOTSET) | ||
| def tearDown(self): | ||
| def teardown_method(self): | ||
| # restore JSON encoder, in case a test changed it | ||
@@ -312,2 +311,6 @@ packet.Packet.json = json | ||
| @s.on('disconnect') | ||
| def baz(sid, reason): | ||
| return sid + reason | ||
| r = s._trigger_event('connect', 1, 2, run_async=False) | ||
@@ -320,3 +323,15 @@ assert r == 3 | ||
| assert r == 'bar' | ||
| r = s._trigger_event('disconnect', 'foo', 'bar') | ||
| assert r == 'foobar' | ||
| def test_trigger_legacy_disconnect_event(self): | ||
| s = server.Server(async_mode='threading') | ||
| @s.on('disconnect') | ||
| def baz(sid): | ||
| return sid | ||
| r = s._trigger_event('disconnect', 'foo', 'bar') | ||
| assert r == 'foo' | ||
| def test_trigger_event_error(self): | ||
@@ -436,2 +451,5 @@ s = server.Server() | ||
| assert 'sid' in packets[0].data | ||
| assert packets[0].data['pingTimeout'] == 20000 | ||
| assert packets[0].data['pingInterval'] == 25000 | ||
| assert packets[0].data['maxPayload'] == 1000000 | ||
@@ -455,3 +473,4 @@ def test_connect_no_upgrades(self): | ||
| def test_connect_custom_ping_times(self): | ||
| s = server.Server(ping_timeout=123, ping_interval=456) | ||
| s = server.Server(ping_timeout=123, ping_interval=456, | ||
| max_http_buffer_size=12345678) | ||
| environ = {'REQUEST_METHOD': 'GET', 'QUERY_STRING': 'EIO=4'} | ||
@@ -463,2 +482,3 @@ start_response = mock.MagicMock() | ||
| assert packets[0].data['pingInterval'] == 456000 | ||
| assert packets[0].data['maxPayload'] == 12345678 | ||
@@ -1111,3 +1131,3 @@ @mock.patch( | ||
| class CustomJSON(object): | ||
| class CustomJSON: | ||
| @staticmethod | ||
@@ -1114,0 +1134,0 @@ def dumps(*args, **kwargs): |
| import io | ||
| import time | ||
| import unittest | ||
| from unittest import mock | ||
@@ -14,4 +13,4 @@ | ||
| class TestSocket(unittest.TestCase): | ||
| def setUp(self): | ||
| class TestSocket: | ||
| def setup_method(self): | ||
| self.bg_tasks = [] | ||
@@ -158,3 +157,4 @@ | ||
| s.send('packet') | ||
| s.close.assert_called_once_with(wait=False, abort=False) | ||
| s.close.assert_called_once_with(wait=False, abort=False, | ||
| reason=mock_server.reason.PING_TIMEOUT) | ||
@@ -297,3 +297,5 @@ def test_polling_read(self): | ||
| s.receive(packet.Packet(packet.CLOSE)) | ||
| s.close.assert_called_once_with(wait=False, abort=True) | ||
| s.close.assert_called_once_with( | ||
| wait=False, abort=True, | ||
| reason=mock_server.reason.CLIENT_DISCONNECT) | ||
@@ -343,3 +345,5 @@ def test_invalid_packet_type(self): | ||
| mock.call('message', 'sid', 'foo', run_async=True), | ||
| mock.call('disconnect', 'sid', run_async=False), | ||
| mock.call('disconnect', 'sid', | ||
| mock_server.reason.SERVER_DISCONNECT, | ||
| run_async=False) | ||
| ] | ||
@@ -377,3 +381,5 @@ ) | ||
| mock.call('message', 'sid', 'foo', run_async=True), | ||
| mock.call('disconnect', 'sid', run_async=False), | ||
| mock.call('disconnect', 'sid', | ||
| mock_server.reason.SERVER_DISCONNECT, | ||
| run_async=False) | ||
| ] | ||
@@ -495,3 +501,5 @@ ) | ||
| mock.call('message', 'sid', foo, run_async=True), | ||
| mock.call('disconnect', 'sid', run_async=False), | ||
| mock.call('disconnect', 'sid', | ||
| mock_server.reason.SERVER_DISCONNECT, | ||
| run_async=False) | ||
| ] | ||
@@ -515,3 +523,4 @@ ) | ||
| mock_server._trigger_event.assert_called_once_with( | ||
| 'disconnect', 'sid', run_async=False | ||
| 'disconnect', 'sid', mock_server.reason.SERVER_DISCONNECT, | ||
| run_async=False | ||
| ) | ||
@@ -518,0 +527,0 @@ s.close() |
+1
-0
@@ -22,2 +22,3 @@ [tox] | ||
| pytest-cov | ||
| pytest-asyncio | ||
| aiohttp | ||
@@ -24,0 +25,0 @@ tornado |
Alert delta unavailable
Currently unable to show alert delta for PyPI packages.
546591
2.14%11651
1.55%