Skip to content

Commit 0d08d9f

Browse files
disconnect reasons for client
1 parent 4c234e3 commit 0d08d9f

File tree

5 files changed

+99
-90
lines changed

5 files changed

+99
-90
lines changed

src/socketio/async_client.py

+24-8
Original file line numberDiff line numberDiff line change
@@ -398,8 +398,9 @@ async def _handle_disconnect(self, namespace):
398398
if not self.connected:
399399
return
400400
namespace = namespace or '/'
401-
await self._trigger_event('disconnect', namespace=namespace)
402-
await self._trigger_event('__disconnect_final', namespace=namespace)
401+
await self._trigger_event('disconnect', namespace,
402+
self.reason.SERVER_DISCONNECT)
403+
await self._trigger_event('__disconnect_final', namespace)
403404
if namespace in self.namespaces:
404405
del self.namespaces[namespace]
405406
if not self.namespaces:
@@ -462,11 +463,27 @@ async def _trigger_event(self, event, namespace, *args):
462463
if handler:
463464
if asyncio.iscoroutinefunction(handler):
464465
try:
465-
ret = await handler(*args)
466+
try:
467+
ret = await handler(*args)
468+
except TypeError:
469+
# the legacy disconnect event does not take a reason
470+
# argument
471+
if event == 'disconnect':
472+
ret = await handler(*args[:-1])
473+
else:
474+
raise
466475
except asyncio.CancelledError: # pragma: no cover
467476
ret = None
468477
else:
469-
ret = handler(*args)
478+
try:
479+
ret = handler(*args)
480+
except TypeError:
481+
# the legacy disconnect event does not take a reason
482+
# argument
483+
if event == 'disconnect':
484+
ret = handler(*args[:-1])
485+
else:
486+
raise
470487
return ret
471488

472489
# or else, forward the event to a namepsace handler if one exists
@@ -566,16 +583,15 @@ async def _handle_eio_message(self, data):
566583
else:
567584
raise ValueError('Unknown packet type.')
568585

569-
async def _handle_eio_disconnect(self):
586+
async def _handle_eio_disconnect(self, reason):
570587
"""Handle the Engine.IO disconnection event."""
571588
self.logger.info('Engine.IO connection dropped')
572589
will_reconnect = self.reconnection and self.eio.state == 'connected'
573590
if self.connected:
574591
for n in self.namespaces:
575-
await self._trigger_event('disconnect', namespace=n)
592+
await self._trigger_event('disconnect', n, reason)
576593
if not will_reconnect:
577-
await self._trigger_event('__disconnect_final',
578-
namespace=n)
594+
await self._trigger_event('__disconnect_final', n)
579595
self.namespaces = {}
580596
self.connected = False
581597
self.callbacks = {}

src/socketio/base_client.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -289,7 +289,7 @@ def _handle_eio_connect(self): # pragma: no cover
289289
def _handle_eio_message(self, data): # pragma: no cover
290290
raise NotImplementedError()
291291

292-
def _handle_eio_disconnect(self): # pragma: no cover
292+
def _handle_eio_disconnect(self, reason): # pragma: no cover
293293
raise NotImplementedError()
294294

295295
def _engineio_client_class(self): # pragma: no cover

src/socketio/client.py

+14-6
Original file line numberDiff line numberDiff line change
@@ -377,8 +377,9 @@ def _handle_disconnect(self, namespace):
377377
if not self.connected:
378378
return
379379
namespace = namespace or '/'
380-
self._trigger_event('disconnect', namespace=namespace)
381-
self._trigger_event('__disconnect_final', namespace=namespace)
380+
self._trigger_event('disconnect', namespace,
381+
self.reason.SERVER_DISCONNECT)
382+
self._trigger_event('__disconnect_final', namespace)
382383
if namespace in self.namespaces:
383384
del self.namespaces[namespace]
384385
if not self.namespaces:
@@ -436,7 +437,14 @@ def _trigger_event(self, event, namespace, *args):
436437
# first see if we have an explicit handler for the event
437438
handler, args = self._get_event_handler(event, namespace, args)
438439
if handler:
439-
return handler(*args)
440+
try:
441+
return handler(*args)
442+
except TypeError:
443+
# the legacy disconnect event does not take a reason argument
444+
if event == 'disconnect':
445+
return handler(*args[:-1])
446+
else:
447+
raise
440448

441449
# or else, forward the event to a namespace handler if one exists
442450
handler, args = self._get_namespace_handler(namespace, args)
@@ -525,15 +533,15 @@ def _handle_eio_message(self, data):
525533
else:
526534
raise ValueError('Unknown packet type.')
527535

528-
def _handle_eio_disconnect(self):
536+
def _handle_eio_disconnect(self, reason):
529537
"""Handle the Engine.IO disconnection event."""
530538
self.logger.info('Engine.IO connection dropped')
531539
will_reconnect = self.reconnection and self.eio.state == 'connected'
532540
if self.connected:
533541
for n in self.namespaces:
534-
self._trigger_event('disconnect', namespace=n)
542+
self._trigger_event('disconnect', n, reason)
535543
if not will_reconnect:
536-
self._trigger_event('__disconnect_final', namespace=n)
544+
self._trigger_event('__disconnect_final', n)
537545
self.namespaces = {}
538546
self.connected = False
539547
self.callbacks = {}

tests/async/test_client.py

+30-42
Original file line numberDiff line numberDiff line change
@@ -600,12 +600,9 @@ def test_handle_disconnect(self):
600600
c.connected = True
601601
c._trigger_event = mock.AsyncMock()
602602
_run(c._handle_disconnect('/'))
603-
c._trigger_event.assert_any_await(
604-
'disconnect', namespace='/'
605-
)
606-
c._trigger_event.assert_any_await(
607-
'__disconnect_final', namespace='/'
608-
)
603+
c._trigger_event.assert_any_await('disconnect', '/',
604+
c.reason.SERVER_DISCONNECT)
605+
c._trigger_event.assert_any_await('__disconnect_final', '/')
609606
assert not c.connected
610607
_run(c._handle_disconnect('/'))
611608
assert c._trigger_event.await_count == 2
@@ -616,21 +613,15 @@ def test_handle_disconnect_namespace(self):
616613
c.namespaces = {'/foo': '1', '/bar': '2'}
617614
c._trigger_event = mock.AsyncMock()
618615
_run(c._handle_disconnect('/foo'))
619-
c._trigger_event.assert_any_await(
620-
'disconnect', namespace='/foo'
621-
)
622-
c._trigger_event.assert_any_await(
623-
'__disconnect_final', namespace='/foo'
624-
)
616+
c._trigger_event.assert_any_await('disconnect', '/foo',
617+
c.reason.SERVER_DISCONNECT)
618+
c._trigger_event.assert_any_await('__disconnect_final', '/foo')
625619
assert c.namespaces == {'/bar': '2'}
626620
assert c.connected
627621
_run(c._handle_disconnect('/bar'))
628-
c._trigger_event.assert_any_await(
629-
'disconnect', namespace='/bar'
630-
)
631-
c._trigger_event.assert_any_await(
632-
'__disconnect_final', namespace='/bar'
633-
)
622+
c._trigger_event.assert_any_await('disconnect', '/bar',
623+
c.reason.SERVER_DISCONNECT)
624+
c._trigger_event.assert_any_await('__disconnect_final', '/bar')
634625
assert c.namespaces == {}
635626
assert not c.connected
636627

@@ -640,12 +631,9 @@ def test_handle_disconnect_unknown_namespace(self):
640631
c.namespaces = {'/foo': '1', '/bar': '2'}
641632
c._trigger_event = mock.AsyncMock()
642633
_run(c._handle_disconnect('/baz'))
643-
c._trigger_event.assert_any_await(
644-
'disconnect', namespace='/baz'
645-
)
646-
c._trigger_event.assert_any_await(
647-
'__disconnect_final', namespace='/baz'
648-
)
634+
c._trigger_event.assert_any_await('disconnect', '/baz',
635+
c.reason.SERVER_DISCONNECT)
636+
c._trigger_event.assert_any_await('__disconnect_final', '/baz')
649637
assert c.namespaces == {'/foo': '1', '/bar': '2'}
650638
assert c.connected
651639

@@ -655,8 +643,9 @@ def test_handle_disconnect_default_namespaces(self):
655643
c.namespaces = {'/foo': '1', '/bar': '2'}
656644
c._trigger_event = mock.AsyncMock()
657645
_run(c._handle_disconnect('/'))
658-
c._trigger_event.assert_any_await('disconnect', namespace='/')
659-
c._trigger_event.assert_any_await('__disconnect_final', namespace='/')
646+
c._trigger_event.assert_any_await('disconnect', '/',
647+
c.reason.SERVER_DISCONNECT)
648+
c._trigger_event.assert_any_await('__disconnect_final', '/')
660649
assert c.namespaces == {'/foo': '1', '/bar': '2'}
661650
assert c.connected
662651

@@ -1152,10 +1141,8 @@ def test_eio_disconnect(self):
11521141
c.start_background_task = mock.MagicMock()
11531142
c.sid = 'foo'
11541143
c.eio.state = 'connected'
1155-
_run(c._handle_eio_disconnect())
1156-
c._trigger_event.assert_awaited_once_with(
1157-
'disconnect', namespace='/'
1158-
)
1144+
_run(c._handle_eio_disconnect('foo'))
1145+
c._trigger_event.assert_awaited_once_with('disconnect', '/', 'foo')
11591146
assert c.sid is None
11601147
assert not c.connected
11611148

@@ -1166,24 +1153,28 @@ def test_eio_disconnect_namespaces(self):
11661153
c._trigger_event = mock.AsyncMock()
11671154
c.sid = 'foo'
11681155
c.eio.state = 'connected'
1169-
_run(c._handle_eio_disconnect())
1170-
c._trigger_event.assert_any_await('disconnect', namespace='/foo')
1171-
c._trigger_event.assert_any_await('disconnect', namespace='/bar')
1156+
_run(c._handle_eio_disconnect(c.reason.CLIENT_DISCONNECT))
1157+
c._trigger_event.assert_any_await('disconnect', '/foo',
1158+
c.reason.CLIENT_DISCONNECT)
1159+
c._trigger_event.assert_any_await('disconnect', '/bar',
1160+
c.reason.CLIENT_DISCONNECT)
1161+
c._trigger_event.asserT_any_await('disconnect', '/',
1162+
c.reason.CLIENT_DISCONNECT)
11721163
assert c.sid is None
11731164
assert not c.connected
11741165

11751166
def test_eio_disconnect_reconnect(self):
11761167
c = async_client.AsyncClient(reconnection=True)
11771168
c.start_background_task = mock.MagicMock()
11781169
c.eio.state = 'connected'
1179-
_run(c._handle_eio_disconnect())
1170+
_run(c._handle_eio_disconnect(c.reason.CLIENT_DISCONNECT))
11801171
c.start_background_task.assert_called_once_with(c._handle_reconnect)
11811172

11821173
def test_eio_disconnect_self_disconnect(self):
11831174
c = async_client.AsyncClient(reconnection=True)
11841175
c.start_background_task = mock.MagicMock()
11851176
c.eio.state = 'disconnected'
1186-
_run(c._handle_eio_disconnect())
1177+
_run(c._handle_eio_disconnect(c.reason.CLIENT_DISCONNECT))
11871178
c.start_background_task.assert_not_called()
11881179

11891180
def test_eio_disconnect_no_reconnect(self):
@@ -1194,13 +1185,10 @@ def test_eio_disconnect_no_reconnect(self):
11941185
c.start_background_task = mock.MagicMock()
11951186
c.sid = 'foo'
11961187
c.eio.state = 'connected'
1197-
_run(c._handle_eio_disconnect())
1198-
c._trigger_event.assert_any_await(
1199-
'disconnect', namespace='/'
1200-
)
1201-
c._trigger_event.assert_any_await(
1202-
'__disconnect_final', namespace='/'
1203-
)
1188+
_run(c._handle_eio_disconnect(c.reason.TRANSPORT_ERROR))
1189+
c._trigger_event.assert_any_await('disconnect', '/',
1190+
c.reason.TRANSPORT_ERROR)
1191+
c._trigger_event.assert_any_await('__disconnect_final', '/')
12041192
assert c.sid is None
12051193
assert not c.connected
12061194
c.start_background_task.assert_not_called()

tests/common/test_client.py

+30-33
Original file line numberDiff line numberDiff line change
@@ -752,8 +752,9 @@ def test_handle_disconnect(self):
752752
c.connected = True
753753
c._trigger_event = mock.MagicMock()
754754
c._handle_disconnect('/')
755-
c._trigger_event.assert_any_call('disconnect', namespace='/')
756-
c._trigger_event.assert_any_call('__disconnect_final', namespace='/')
755+
c._trigger_event.assert_any_call('disconnect', '/',
756+
c.reason.SERVER_DISCONNECT)
757+
c._trigger_event.assert_any_call('__disconnect_final', '/')
757758
assert not c.connected
758759
c._handle_disconnect('/')
759760
assert c._trigger_event.call_count == 2
@@ -764,21 +765,15 @@ def test_handle_disconnect_namespace(self):
764765
c.namespaces = {'/foo': '1', '/bar': '2'}
765766
c._trigger_event = mock.MagicMock()
766767
c._handle_disconnect('/foo')
767-
c._trigger_event.assert_any_call(
768-
'disconnect', namespace='/foo'
769-
)
770-
c._trigger_event.assert_any_call(
771-
'__disconnect_final', namespace='/foo'
772-
)
768+
c._trigger_event.assert_any_call('disconnect', '/foo',
769+
c.reason.SERVER_DISCONNECT)
770+
c._trigger_event.assert_any_call('__disconnect_final', '/foo')
773771
assert c.namespaces == {'/bar': '2'}
774772
assert c.connected
775773
c._handle_disconnect('/bar')
776-
c._trigger_event.assert_any_call(
777-
'disconnect', namespace='/bar'
778-
)
779-
c._trigger_event.assert_any_call(
780-
'__disconnect_final', namespace='/bar'
781-
)
774+
c._trigger_event.assert_any_call('disconnect', '/bar',
775+
c.reason.SERVER_DISCONNECT)
776+
c._trigger_event.assert_any_call('__disconnect_final', '/bar')
782777
assert c.namespaces == {}
783778
assert not c.connected
784779

@@ -788,12 +783,9 @@ def test_handle_disconnect_unknown_namespace(self):
788783
c.namespaces = {'/foo': '1', '/bar': '2'}
789784
c._trigger_event = mock.MagicMock()
790785
c._handle_disconnect('/baz')
791-
c._trigger_event.assert_any_call(
792-
'disconnect', namespace='/baz'
793-
)
794-
c._trigger_event.assert_any_call(
795-
'__disconnect_final', namespace='/baz'
796-
)
786+
c._trigger_event.assert_any_call('disconnect', '/baz',
787+
c.reason.SERVER_DISCONNECT)
788+
c._trigger_event.assert_any_call('__disconnect_final', '/baz')
797789
assert c.namespaces == {'/foo': '1', '/bar': '2'}
798790
assert c.connected
799791

@@ -804,8 +796,9 @@ def test_handle_disconnect_default_namespace(self):
804796
c._trigger_event = mock.MagicMock()
805797
c._handle_disconnect('/')
806798
print(c._trigger_event.call_args_list)
807-
c._trigger_event.assert_any_call('disconnect', namespace='/')
808-
c._trigger_event.assert_any_call('__disconnect_final', namespace='/')
799+
c._trigger_event.assert_any_call('disconnect', '/',
800+
c.reason.SERVER_DISCONNECT)
801+
c._trigger_event.assert_any_call('__disconnect_final', '/')
809802
assert c.namespaces == {'/foo': '1', '/bar': '2'}
810803
assert c.connected
811804

@@ -1286,8 +1279,8 @@ def test_eio_disconnect(self):
12861279
c.start_background_task = mock.MagicMock()
12871280
c.sid = 'foo'
12881281
c.eio.state = 'connected'
1289-
c._handle_eio_disconnect()
1290-
c._trigger_event.assert_called_once_with('disconnect', namespace='/')
1282+
c._handle_eio_disconnect('foo')
1283+
c._trigger_event.assert_called_once_with('disconnect', '/', 'foo')
12911284
assert c.sid is None
12921285
assert not c.connected
12931286

@@ -1299,25 +1292,28 @@ def test_eio_disconnect_namespaces(self):
12991292
c.start_background_task = mock.MagicMock()
13001293
c.sid = 'foo'
13011294
c.eio.state = 'connected'
1302-
c._handle_eio_disconnect()
1303-
c._trigger_event.assert_any_call('disconnect', namespace='/foo')
1304-
c._trigger_event.assert_any_call('disconnect', namespace='/bar')
1305-
c._trigger_event.assert_any_call('disconnect', namespace='/')
1295+
c._handle_eio_disconnect(c.reason.CLIENT_DISCONNECT)
1296+
c._trigger_event.assert_any_call('disconnect', '/foo',
1297+
c.reason.CLIENT_DISCONNECT)
1298+
c._trigger_event.assert_any_call('disconnect', '/bar',
1299+
c.reason.CLIENT_DISCONNECT)
1300+
c._trigger_event.assert_any_call('disconnect', '/',
1301+
c.reason.CLIENT_DISCONNECT)
13061302
assert c.sid is None
13071303
assert not c.connected
13081304

13091305
def test_eio_disconnect_reconnect(self):
13101306
c = client.Client(reconnection=True)
13111307
c.start_background_task = mock.MagicMock()
13121308
c.eio.state = 'connected'
1313-
c._handle_eio_disconnect()
1309+
c._handle_eio_disconnect(c.reason.CLIENT_DISCONNECT)
13141310
c.start_background_task.assert_called_once_with(c._handle_reconnect)
13151311

13161312
def test_eio_disconnect_self_disconnect(self):
13171313
c = client.Client(reconnection=True)
13181314
c.start_background_task = mock.MagicMock()
13191315
c.eio.state = 'disconnected'
1320-
c._handle_eio_disconnect()
1316+
c._handle_eio_disconnect(c.reason.CLIENT_DISCONNECT)
13211317
c.start_background_task.assert_not_called()
13221318

13231319
def test_eio_disconnect_no_reconnect(self):
@@ -1328,9 +1324,10 @@ def test_eio_disconnect_no_reconnect(self):
13281324
c.start_background_task = mock.MagicMock()
13291325
c.sid = 'foo'
13301326
c.eio.state = 'connected'
1331-
c._handle_eio_disconnect()
1332-
c._trigger_event.assert_any_call('disconnect', namespace='/')
1333-
c._trigger_event.assert_any_call('__disconnect_final', namespace='/')
1327+
c._handle_eio_disconnect(c.reason.TRANSPORT_ERROR)
1328+
c._trigger_event.assert_any_call('disconnect', '/',
1329+
c.reason.TRANSPORT_ERROR)
1330+
c._trigger_event.assert_any_call('__disconnect_final', '/')
13341331
assert c.sid is None
13351332
assert not c.connected
13361333
c.start_background_task.assert_not_called()

0 commit comments

Comments
 (0)