🚨 Latest Research:Tanstack npm Packages Compromised in Ongoing Mini Shai-Hulud Supply-Chain Attack.Learn More
Socket
Book a DemoSign in
Socket

python-engineio

Package Overview
Dependencies
Maintainers
1
Versions
143
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

python-engineio - pypi Package Compare versions

Comparing version
4.10.1
to
4.11.0
+17
-6
docs/client.rst

@@ -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 @@ ----------------------

@@ -1,2 +0,1 @@

# -*- coding: utf-8 -*-
#

@@ -3,0 +2,0 @@ # Configuration file for the Sphinx documentation builder.

@@ -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 @@ ----------------

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>

[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

@@ -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()

@@ -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')
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()

@@ -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')

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()

@@ -22,2 +22,3 @@ [tox]

pytest-cov
pytest-asyncio
aiohttp

@@ -24,0 +25,0 @@ tornado