Skip to content

Commit c279f26

Browse files
Support multiple arguments via pubsub emits (Fixes #1539) (#1540)
1 parent 91553c1 commit c279f26

File tree

4 files changed

+422
-20
lines changed

4 files changed

+422
-20
lines changed

src/socketio/async_pubsub_manager.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,10 @@ async def emit(self, event, data, namespace=None, room=None, skip_sid=None,
6666
callback = (room, namespace, id)
6767
else:
6868
callback = None
69+
if isinstance(data, tuple):
70+
data = list(data)
71+
else:
72+
data = [data]
6973
binary = Packet.data_is_binary(data)
7074
if binary:
7175
data, attachments = Packet.deconstruct_binary(data)
@@ -155,6 +159,11 @@ async def _handle_emit(self, message):
155159
if message.get('binary'):
156160
attachments = [base64.b64decode(a) for a in data[1:]]
157161
data = Packet.reconstruct_binary(data[0], attachments)
162+
if isinstance(data, list):
163+
if len(data) == 1:
164+
data = data[0]
165+
else:
166+
data = tuple(data)
158167
await super().emit(message['event'], data,
159168
namespace=message.get('namespace'),
160169
room=message.get('room'),

src/socketio/pubsub_manager.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,10 @@ def emit(self, event, data, namespace=None, room=None, skip_sid=None,
6363
callback = (room, namespace, id)
6464
else:
6565
callback = None
66+
if isinstance(data, tuple):
67+
data = list(data)
68+
else:
69+
data = [data]
6670
binary = Packet.data_is_binary(data)
6771
if binary:
6872
data, attachments = Packet.deconstruct_binary(data)
@@ -151,6 +155,11 @@ def _handle_emit(self, message):
151155
if message.get('binary'):
152156
attachments = [base64.b64decode(a) for a in data[1:]]
153157
data = Packet.reconstruct_binary(data[0], attachments)
158+
if isinstance(data, list):
159+
if len(data) == 1:
160+
data = data[0]
161+
else:
162+
data = tuple(data)
154163
super().emit(message['event'], data,
155164
namespace=message.get('namespace'),
156165
room=message.get('room'),

tests/async/test_pubsub_manager.py

Lines changed: 207 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ async def test_emit(self):
5858
'method': 'emit',
5959
'event': 'foo',
6060
'binary': False,
61-
'data': 'bar',
61+
'data': ['bar'],
6262
'namespace': '/',
6363
'room': None,
6464
'skip_sid': None,
@@ -74,7 +74,7 @@ async def test_emit_binary(self):
7474
'method': 'emit',
7575
'event': 'foo',
7676
'binary': True,
77-
'data': [{'_placeholder': True, 'num': 0}, 'YmFy'],
77+
'data': [[{'_placeholder': True, 'num': 0}], 'YmFy'],
7878
'namespace': '/',
7979
'room': None,
8080
'skip_sid': None,
@@ -88,7 +88,7 @@ async def test_emit_binary(self):
8888
'method': 'emit',
8989
'event': 'foo',
9090
'binary': True,
91-
'data': [{'foo': {'_placeholder': True, 'num': 0}}, 'YmFy'],
91+
'data': [[{'foo': {'_placeholder': True, 'num': 0}}], 'YmFy'],
9292
'namespace': '/',
9393
'room': None,
9494
'skip_sid': None,
@@ -104,7 +104,7 @@ async def test_emit_bytearray(self):
104104
'method': 'emit',
105105
'event': 'foo',
106106
'binary': True,
107-
'data': [{'_placeholder': True, 'num': 0}, 'YmFy'],
107+
'data': [[{'_placeholder': True, 'num': 0}], 'YmFy'],
108108
'namespace': '/',
109109
'room': None,
110110
'skip_sid': None,
@@ -118,7 +118,87 @@ async def test_emit_bytearray(self):
118118
'method': 'emit',
119119
'event': 'foo',
120120
'binary': True,
121-
'data': [{'foo': {'_placeholder': True, 'num': 0}}, 'YmFy'],
121+
'data': [[{'foo': {'_placeholder': True, 'num': 0}}], 'YmFy'],
122+
'namespace': '/',
123+
'room': None,
124+
'skip_sid': None,
125+
'callback': None,
126+
'host_id': '123456',
127+
}
128+
)
129+
130+
async def test_emit_list(self):
131+
await self.pm.emit('foo', [1, 'two'])
132+
self.pm._publish.assert_awaited_once_with(
133+
{
134+
'method': 'emit',
135+
'event': 'foo',
136+
'binary': False,
137+
'data': [[1, 'two']],
138+
'namespace': '/',
139+
'room': None,
140+
'skip_sid': None,
141+
'callback': None,
142+
'host_id': '123456',
143+
}
144+
)
145+
await self.pm.emit('foo', [1, b'two', 'three'])
146+
self.pm._publish.assert_awaited_with(
147+
{
148+
'method': 'emit',
149+
'event': 'foo',
150+
'binary': True,
151+
'data': [
152+
[[1, {'_placeholder': True, 'num': 0}, 'three']], 'dHdv',
153+
],
154+
'namespace': '/',
155+
'room': None,
156+
'skip_sid': None,
157+
'callback': None,
158+
'host_id': '123456',
159+
}
160+
)
161+
162+
async def test_emit_no_arguments(self):
163+
await self.pm.emit('foo', ())
164+
self.pm._publish.assert_awaited_once_with(
165+
{
166+
'method': 'emit',
167+
'event': 'foo',
168+
'binary': False,
169+
'data': [],
170+
'namespace': '/',
171+
'room': None,
172+
'skip_sid': None,
173+
'callback': None,
174+
'host_id': '123456',
175+
}
176+
)
177+
178+
async def test_emit_multiple_arguments(self):
179+
await self.pm.emit('foo', (1, 'two'))
180+
self.pm._publish.assert_awaited_once_with(
181+
{
182+
'method': 'emit',
183+
'event': 'foo',
184+
'binary': False,
185+
'data': [1, 'two'],
186+
'namespace': '/',
187+
'room': None,
188+
'skip_sid': None,
189+
'callback': None,
190+
'host_id': '123456',
191+
}
192+
)
193+
await self.pm.emit('foo', (1, b'two', 'three'))
194+
self.pm._publish.assert_awaited_with(
195+
{
196+
'method': 'emit',
197+
'event': 'foo',
198+
'binary': True,
199+
'data': [
200+
[1, {'_placeholder': True, 'num': 0}, 'three'], 'dHdv',
201+
],
122202
'namespace': '/',
123203
'room': None,
124204
'skip_sid': None,
@@ -135,7 +215,7 @@ async def test_emit_with_to(self):
135215
'method': 'emit',
136216
'event': 'foo',
137217
'binary': False,
138-
'data': 'bar',
218+
'data': ['bar'],
139219
'namespace': '/',
140220
'room': sid,
141221
'skip_sid': None,
@@ -151,7 +231,7 @@ async def test_emit_with_namespace(self):
151231
'method': 'emit',
152232
'event': 'foo',
153233
'binary': False,
154-
'data': 'bar',
234+
'data': ['bar'],
155235
'namespace': '/baz',
156236
'room': None,
157237
'skip_sid': None,
@@ -167,7 +247,7 @@ async def test_emit_with_room(self):
167247
'method': 'emit',
168248
'event': 'foo',
169249
'binary': False,
170-
'data': 'bar',
250+
'data': ['bar'],
171251
'namespace': '/',
172252
'room': 'baz',
173253
'skip_sid': None,
@@ -183,7 +263,7 @@ async def test_emit_with_skip_sid(self):
183263
'method': 'emit',
184264
'event': 'foo',
185265
'binary': False,
186-
'data': 'bar',
266+
'data': ['bar'],
187267
'namespace': '/',
188268
'room': None,
189269
'skip_sid': 'baz',
@@ -202,7 +282,7 @@ async def test_emit_with_callback(self):
202282
'method': 'emit',
203283
'event': 'foo',
204284
'binary': False,
205-
'data': 'bar',
285+
'data': ['bar'],
206286
'namespace': '/',
207287
'room': 'baz',
208288
'skip_sid': None,
@@ -294,6 +374,20 @@ async def test_close_room_with_namespace(self):
294374
)
295375

296376
async def test_handle_emit(self):
377+
with mock.patch.object(
378+
async_manager.AsyncManager, 'emit'
379+
) as super_emit:
380+
await self.pm._handle_emit({'event': 'foo', 'data': ['bar']})
381+
super_emit.assert_awaited_once_with(
382+
'foo',
383+
'bar',
384+
namespace=None,
385+
room=None,
386+
skip_sid=None,
387+
callback=None,
388+
)
389+
390+
async def test_handle_legacy_emit(self):
297391
with mock.patch.object(
298392
async_manager.AsyncManager, 'emit'
299393
) as super_emit:
@@ -308,6 +402,37 @@ async def test_handle_emit(self):
308402
)
309403

310404
async def test_handle_emit_binary(self):
405+
with mock.patch.object(
406+
async_manager.AsyncManager, 'emit'
407+
) as super_emit:
408+
await self.pm._handle_emit({
409+
'event': 'foo',
410+
'binary': True,
411+
'data': [[{'_placeholder': True, 'num': 0}], 'YmFy'],
412+
})
413+
super_emit.assert_awaited_once_with(
414+
'foo',
415+
b'bar',
416+
namespace=None,
417+
room=None,
418+
skip_sid=None,
419+
callback=None,
420+
)
421+
await self.pm._handle_emit({
422+
'event': 'foo',
423+
'binary': True,
424+
'data': [[{'foo': {'_placeholder': True, 'num': 0}}], 'YmFy'],
425+
})
426+
super_emit.assert_awaited_with(
427+
'foo',
428+
{'foo': b'bar'},
429+
namespace=None,
430+
room=None,
431+
skip_sid=None,
432+
callback=None,
433+
)
434+
435+
async def test_handle_legacy_emit_binary(self):
311436
with mock.patch.object(
312437
async_manager.AsyncManager, 'emit'
313438
) as super_emit:
@@ -338,6 +463,78 @@ async def test_handle_emit_binary(self):
338463
callback=None,
339464
)
340465

466+
async def test_handle_emit_list(self):
467+
with mock.patch.object(
468+
async_manager.AsyncManager, 'emit'
469+
) as super_emit:
470+
await self.pm._handle_emit({'event': 'foo', 'data': [[1, 'two']]})
471+
super_emit.assert_awaited_once_with(
472+
'foo',
473+
[1, 'two'],
474+
namespace=None,
475+
room=None,
476+
skip_sid=None,
477+
callback=None,
478+
)
479+
await self.pm._handle_emit({
480+
'event': 'foo',
481+
'binary': True,
482+
'data': [
483+
[[1, {'_placeholder': True, 'num': 0}, 'three']], 'dHdv'
484+
]
485+
})
486+
super_emit.assert_awaited_with(
487+
'foo',
488+
[1, b'two', 'three'],
489+
namespace=None,
490+
room=None,
491+
skip_sid=None,
492+
callback=None,
493+
)
494+
495+
async def test_handle_emit_no_arguments(self):
496+
with mock.patch.object(
497+
async_manager.AsyncManager, 'emit'
498+
) as super_emit:
499+
await self.pm._handle_emit({'event': 'foo', 'data': []})
500+
super_emit.assert_awaited_once_with(
501+
'foo',
502+
(),
503+
namespace=None,
504+
room=None,
505+
skip_sid=None,
506+
callback=None,
507+
)
508+
509+
async def test_handle_emit_multiple_arguments(self):
510+
with mock.patch.object(
511+
async_manager.AsyncManager, 'emit'
512+
) as super_emit:
513+
await self.pm._handle_emit({'event': 'foo', 'data': [1, 'two']})
514+
super_emit.assert_awaited_once_with(
515+
'foo',
516+
(1, 'two'),
517+
namespace=None,
518+
room=None,
519+
skip_sid=None,
520+
callback=None,
521+
)
522+
await self.pm._handle_emit({
523+
'event': 'foo',
524+
'binary': True,
525+
'data': [
526+
[1, {'_placeholder': True, 'num': 0}, 'three'], 'dHdv'
527+
]
528+
})
529+
super_emit.assert_awaited_with(
530+
'foo',
531+
(1, b'two', 'three'),
532+
namespace=None,
533+
room=None,
534+
skip_sid=None,
535+
callback=None,
536+
)
537+
341538
async def test_handle_emit_with_namespace(self):
342539
with mock.patch.object(
343540
async_manager.AsyncManager, 'emit'

0 commit comments

Comments
 (0)