Browse Source

Support multiple arguments via pubsub emits (Fixes #1539) (#1540)

pull/1542/head
Miguel Grinberg 6 months ago
committed by GitHub
parent
commit
c279f26bb8
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 9
      src/socketio/async_pubsub_manager.py
  2. 9
      src/socketio/pubsub_manager.py
  3. 217
      tests/async/test_pubsub_manager.py
  4. 207
      tests/common/test_pubsub_manager.py

9
src/socketio/async_pubsub_manager.py

@ -66,6 +66,10 @@ class AsyncPubSubManager(AsyncManager):
callback = (room, namespace, id)
else:
callback = None
if isinstance(data, tuple):
data = list(data)
else:
data = [data]
binary = Packet.data_is_binary(data)
if binary:
data, attachments = Packet.deconstruct_binary(data)
@ -155,6 +159,11 @@ class AsyncPubSubManager(AsyncManager):
if message.get('binary'):
attachments = [base64.b64decode(a) for a in data[1:]]
data = Packet.reconstruct_binary(data[0], attachments)
if isinstance(data, list):
if len(data) == 1:
data = data[0]
else:
data = tuple(data)
await super().emit(message['event'], data,
namespace=message.get('namespace'),
room=message.get('room'),

9
src/socketio/pubsub_manager.py

@ -63,6 +63,10 @@ class PubSubManager(Manager):
callback = (room, namespace, id)
else:
callback = None
if isinstance(data, tuple):
data = list(data)
else:
data = [data]
binary = Packet.data_is_binary(data)
if binary:
data, attachments = Packet.deconstruct_binary(data)
@ -151,6 +155,11 @@ class PubSubManager(Manager):
if message.get('binary'):
attachments = [base64.b64decode(a) for a in data[1:]]
data = Packet.reconstruct_binary(data[0], attachments)
if isinstance(data, list):
if len(data) == 1:
data = data[0]
else:
data = tuple(data)
super().emit(message['event'], data,
namespace=message.get('namespace'),
room=message.get('room'),

217
tests/async/test_pubsub_manager.py

@ -58,7 +58,7 @@ class TestAsyncPubSubManager:
'method': 'emit',
'event': 'foo',
'binary': False,
'data': 'bar',
'data': ['bar'],
'namespace': '/',
'room': None,
'skip_sid': None,
@ -74,7 +74,7 @@ class TestAsyncPubSubManager:
'method': 'emit',
'event': 'foo',
'binary': True,
'data': [{'_placeholder': True, 'num': 0}, 'YmFy'],
'data': [[{'_placeholder': True, 'num': 0}], 'YmFy'],
'namespace': '/',
'room': None,
'skip_sid': None,
@ -88,7 +88,7 @@ class TestAsyncPubSubManager:
'method': 'emit',
'event': 'foo',
'binary': True,
'data': [{'foo': {'_placeholder': True, 'num': 0}}, 'YmFy'],
'data': [[{'foo': {'_placeholder': True, 'num': 0}}], 'YmFy'],
'namespace': '/',
'room': None,
'skip_sid': None,
@ -104,7 +104,7 @@ class TestAsyncPubSubManager:
'method': 'emit',
'event': 'foo',
'binary': True,
'data': [{'_placeholder': True, 'num': 0}, 'YmFy'],
'data': [[{'_placeholder': True, 'num': 0}], 'YmFy'],
'namespace': '/',
'room': None,
'skip_sid': None,
@ -118,7 +118,87 @@ class TestAsyncPubSubManager:
'method': 'emit',
'event': 'foo',
'binary': True,
'data': [{'foo': {'_placeholder': True, 'num': 0}}, 'YmFy'],
'data': [[{'foo': {'_placeholder': True, 'num': 0}}], 'YmFy'],
'namespace': '/',
'room': None,
'skip_sid': None,
'callback': None,
'host_id': '123456',
}
)
async def test_emit_list(self):
await self.pm.emit('foo', [1, 'two'])
self.pm._publish.assert_awaited_once_with(
{
'method': 'emit',
'event': 'foo',
'binary': False,
'data': [[1, 'two']],
'namespace': '/',
'room': None,
'skip_sid': None,
'callback': None,
'host_id': '123456',
}
)
await self.pm.emit('foo', [1, b'two', 'three'])
self.pm._publish.assert_awaited_with(
{
'method': 'emit',
'event': 'foo',
'binary': True,
'data': [
[[1, {'_placeholder': True, 'num': 0}, 'three']], 'dHdv',
],
'namespace': '/',
'room': None,
'skip_sid': None,
'callback': None,
'host_id': '123456',
}
)
async def test_emit_no_arguments(self):
await self.pm.emit('foo', ())
self.pm._publish.assert_awaited_once_with(
{
'method': 'emit',
'event': 'foo',
'binary': False,
'data': [],
'namespace': '/',
'room': None,
'skip_sid': None,
'callback': None,
'host_id': '123456',
}
)
async def test_emit_multiple_arguments(self):
await self.pm.emit('foo', (1, 'two'))
self.pm._publish.assert_awaited_once_with(
{
'method': 'emit',
'event': 'foo',
'binary': False,
'data': [1, 'two'],
'namespace': '/',
'room': None,
'skip_sid': None,
'callback': None,
'host_id': '123456',
}
)
await self.pm.emit('foo', (1, b'two', 'three'))
self.pm._publish.assert_awaited_with(
{
'method': 'emit',
'event': 'foo',
'binary': True,
'data': [
[1, {'_placeholder': True, 'num': 0}, 'three'], 'dHdv',
],
'namespace': '/',
'room': None,
'skip_sid': None,
@ -135,7 +215,7 @@ class TestAsyncPubSubManager:
'method': 'emit',
'event': 'foo',
'binary': False,
'data': 'bar',
'data': ['bar'],
'namespace': '/',
'room': sid,
'skip_sid': None,
@ -151,7 +231,7 @@ class TestAsyncPubSubManager:
'method': 'emit',
'event': 'foo',
'binary': False,
'data': 'bar',
'data': ['bar'],
'namespace': '/baz',
'room': None,
'skip_sid': None,
@ -167,7 +247,7 @@ class TestAsyncPubSubManager:
'method': 'emit',
'event': 'foo',
'binary': False,
'data': 'bar',
'data': ['bar'],
'namespace': '/',
'room': 'baz',
'skip_sid': None,
@ -183,7 +263,7 @@ class TestAsyncPubSubManager:
'method': 'emit',
'event': 'foo',
'binary': False,
'data': 'bar',
'data': ['bar'],
'namespace': '/',
'room': None,
'skip_sid': 'baz',
@ -202,7 +282,7 @@ class TestAsyncPubSubManager:
'method': 'emit',
'event': 'foo',
'binary': False,
'data': 'bar',
'data': ['bar'],
'namespace': '/',
'room': 'baz',
'skip_sid': None,
@ -294,6 +374,20 @@ class TestAsyncPubSubManager:
)
async def test_handle_emit(self):
with mock.patch.object(
async_manager.AsyncManager, 'emit'
) as super_emit:
await self.pm._handle_emit({'event': 'foo', 'data': ['bar']})
super_emit.assert_awaited_once_with(
'foo',
'bar',
namespace=None,
room=None,
skip_sid=None,
callback=None,
)
async def test_handle_legacy_emit(self):
with mock.patch.object(
async_manager.AsyncManager, 'emit'
) as super_emit:
@ -308,6 +402,37 @@ class TestAsyncPubSubManager:
)
async def test_handle_emit_binary(self):
with mock.patch.object(
async_manager.AsyncManager, 'emit'
) as super_emit:
await self.pm._handle_emit({
'event': 'foo',
'binary': True,
'data': [[{'_placeholder': True, 'num': 0}], 'YmFy'],
})
super_emit.assert_awaited_once_with(
'foo',
b'bar',
namespace=None,
room=None,
skip_sid=None,
callback=None,
)
await self.pm._handle_emit({
'event': 'foo',
'binary': True,
'data': [[{'foo': {'_placeholder': True, 'num': 0}}], 'YmFy'],
})
super_emit.assert_awaited_with(
'foo',
{'foo': b'bar'},
namespace=None,
room=None,
skip_sid=None,
callback=None,
)
async def test_handle_legacy_emit_binary(self):
with mock.patch.object(
async_manager.AsyncManager, 'emit'
) as super_emit:
@ -338,6 +463,78 @@ class TestAsyncPubSubManager:
callback=None,
)
async def test_handle_emit_list(self):
with mock.patch.object(
async_manager.AsyncManager, 'emit'
) as super_emit:
await self.pm._handle_emit({'event': 'foo', 'data': [[1, 'two']]})
super_emit.assert_awaited_once_with(
'foo',
[1, 'two'],
namespace=None,
room=None,
skip_sid=None,
callback=None,
)
await self.pm._handle_emit({
'event': 'foo',
'binary': True,
'data': [
[[1, {'_placeholder': True, 'num': 0}, 'three']], 'dHdv'
]
})
super_emit.assert_awaited_with(
'foo',
[1, b'two', 'three'],
namespace=None,
room=None,
skip_sid=None,
callback=None,
)
async def test_handle_emit_no_arguments(self):
with mock.patch.object(
async_manager.AsyncManager, 'emit'
) as super_emit:
await self.pm._handle_emit({'event': 'foo', 'data': []})
super_emit.assert_awaited_once_with(
'foo',
(),
namespace=None,
room=None,
skip_sid=None,
callback=None,
)
async def test_handle_emit_multiple_arguments(self):
with mock.patch.object(
async_manager.AsyncManager, 'emit'
) as super_emit:
await self.pm._handle_emit({'event': 'foo', 'data': [1, 'two']})
super_emit.assert_awaited_once_with(
'foo',
(1, 'two'),
namespace=None,
room=None,
skip_sid=None,
callback=None,
)
await self.pm._handle_emit({
'event': 'foo',
'binary': True,
'data': [
[1, {'_placeholder': True, 'num': 0}, 'three'], 'dHdv'
]
})
super_emit.assert_awaited_with(
'foo',
(1, b'two', 'three'),
namespace=None,
room=None,
skip_sid=None,
callback=None,
)
async def test_handle_emit_with_namespace(self):
with mock.patch.object(
async_manager.AsyncManager, 'emit'

207
tests/common/test_pubsub_manager.py

@ -70,7 +70,7 @@ class TestPubSubManager:
'method': 'emit',
'event': 'foo',
'binary': False,
'data': 'bar',
'data': ['bar'],
'namespace': '/',
'room': None,
'skip_sid': None,
@ -86,7 +86,7 @@ class TestPubSubManager:
'method': 'emit',
'event': 'foo',
'binary': True,
'data': [{'_placeholder': True, 'num': 0}, 'YmFy'],
'data': [[{'_placeholder': True, 'num': 0}], 'YmFy'],
'namespace': '/',
'room': None,
'skip_sid': None,
@ -100,7 +100,7 @@ class TestPubSubManager:
'method': 'emit',
'event': 'foo',
'binary': True,
'data': [{'foo': {'_placeholder': True, 'num': 0}}, 'YmFy'],
'data': [[{'foo': {'_placeholder': True, 'num': 0}}], 'YmFy'],
'namespace': '/',
'room': None,
'skip_sid': None,
@ -116,7 +116,7 @@ class TestPubSubManager:
'method': 'emit',
'event': 'foo',
'binary': True,
'data': [{'_placeholder': True, 'num': 0}, 'YmFy'],
'data': [[{'_placeholder': True, 'num': 0}], 'YmFy'],
'namespace': '/',
'room': None,
'skip_sid': None,
@ -130,7 +130,87 @@ class TestPubSubManager:
'method': 'emit',
'event': 'foo',
'binary': True,
'data': [{'foo': {'_placeholder': True, 'num': 0}}, 'YmFy'],
'data': [[{'foo': {'_placeholder': True, 'num': 0}}], 'YmFy'],
'namespace': '/',
'room': None,
'skip_sid': None,
'callback': None,
'host_id': '123456',
}
)
def test_emit_list(self):
self.pm.emit('foo', [1, 'two'])
self.pm._publish.assert_called_once_with(
{
'method': 'emit',
'event': 'foo',
'binary': False,
'data': [[1, 'two']],
'namespace': '/',
'room': None,
'skip_sid': None,
'callback': None,
'host_id': '123456',
}
)
self.pm.emit('foo', [1, b'two', 'three'])
self.pm._publish.assert_called_with(
{
'method': 'emit',
'event': 'foo',
'binary': True,
'data': [
[[1, {'_placeholder': True, 'num': 0}, 'three']], 'dHdv',
],
'namespace': '/',
'room': None,
'skip_sid': None,
'callback': None,
'host_id': '123456',
}
)
def test_emit_no_arguments(self):
self.pm.emit('foo', ())
self.pm._publish.assert_called_once_with(
{
'method': 'emit',
'event': 'foo',
'binary': False,
'data': [],
'namespace': '/',
'room': None,
'skip_sid': None,
'callback': None,
'host_id': '123456',
}
)
def test_emit_multiple_arguments(self):
self.pm.emit('foo', (1, 'two'))
self.pm._publish.assert_called_once_with(
{
'method': 'emit',
'event': 'foo',
'binary': False,
'data': [1, 'two'],
'namespace': '/',
'room': None,
'skip_sid': None,
'callback': None,
'host_id': '123456',
}
)
self.pm.emit('foo', (1, b'two', 'three'))
self.pm._publish.assert_called_with(
{
'method': 'emit',
'event': 'foo',
'binary': True,
'data': [
[1, {'_placeholder': True, 'num': 0}, 'three'], 'dHdv',
],
'namespace': '/',
'room': None,
'skip_sid': None,
@ -147,7 +227,7 @@ class TestPubSubManager:
'method': 'emit',
'event': 'foo',
'binary': False,
'data': 'bar',
'data': ['bar'],
'namespace': '/',
'room': sid,
'skip_sid': None,
@ -163,7 +243,7 @@ class TestPubSubManager:
'method': 'emit',
'event': 'foo',
'binary': False,
'data': 'bar',
'data': ['bar'],
'namespace': '/baz',
'room': None,
'skip_sid': None,
@ -179,7 +259,7 @@ class TestPubSubManager:
'method': 'emit',
'event': 'foo',
'binary': False,
'data': 'bar',
'data': ['bar'],
'namespace': '/',
'room': 'baz',
'skip_sid': None,
@ -195,7 +275,7 @@ class TestPubSubManager:
'method': 'emit',
'event': 'foo',
'binary': False,
'data': 'bar',
'data': ['bar'],
'namespace': '/',
'room': None,
'skip_sid': 'baz',
@ -214,7 +294,7 @@ class TestPubSubManager:
'method': 'emit',
'event': 'foo',
'binary': False,
'data': 'bar',
'data': ['bar'],
'namespace': '/',
'room': 'baz',
'skip_sid': None,
@ -305,6 +385,18 @@ class TestPubSubManager:
)
def test_handle_emit(self):
with mock.patch.object(manager.Manager, 'emit') as super_emit:
self.pm._handle_emit({'event': 'foo', 'data': ['bar']})
super_emit.assert_called_once_with(
'foo',
'bar',
namespace=None,
room=None,
skip_sid=None,
callback=None,
)
def test_handle_legacy_emit(self):
with mock.patch.object(manager.Manager, 'emit') as super_emit:
self.pm._handle_emit({'event': 'foo', 'data': 'bar'})
super_emit.assert_called_once_with(
@ -317,6 +409,35 @@ class TestPubSubManager:
)
def test_handle_emit_binary(self):
with mock.patch.object(manager.Manager, 'emit') as super_emit:
self.pm._handle_emit({
'event': 'foo',
'binary': True,
'data': [[{'_placeholder': True, 'num': 0}], 'YmFy'],
})
super_emit.assert_called_once_with(
'foo',
b'bar',
namespace=None,
room=None,
skip_sid=None,
callback=None,
)
self.pm._handle_emit({
'event': 'foo',
'binary': True,
'data': [[{'foo': {'_placeholder': True, 'num': 0}}], 'YmFy'],
})
super_emit.assert_called_with(
'foo',
{'foo': b'bar'},
namespace=None,
room=None,
skip_sid=None,
callback=None,
)
def test_handle_legacy_emit_binary(self):
with mock.patch.object(manager.Manager, 'emit') as super_emit:
self.pm._handle_emit({
'event': 'foo',
@ -345,6 +466,72 @@ class TestPubSubManager:
callback=None,
)
def test_handle_emit_list(self):
with mock.patch.object(manager.Manager, 'emit') as super_emit:
self.pm._handle_emit({'event': 'foo', 'data': [[1, 'two']]})
super_emit.assert_called_once_with(
'foo',
[1, 'two'],
namespace=None,
room=None,
skip_sid=None,
callback=None,
)
self.pm._handle_emit({
'event': 'foo',
'binary': True,
'data': [
[[1, {'_placeholder': True, 'num': 0}, 'three']], 'dHdv'
],
})
super_emit.assert_called_with(
'foo',
[1, b'two', 'three'],
namespace=None,
room=None,
skip_sid=None,
callback=None,
)
def test_handle_emit_no_arguments(self):
with mock.patch.object(manager.Manager, 'emit') as super_emit:
self.pm._handle_emit({'event': 'foo', 'data': []})
super_emit.assert_called_once_with(
'foo',
(),
namespace=None,
room=None,
skip_sid=None,
callback=None,
)
def test_handle_emit_multiple_arguments(self):
with mock.patch.object(manager.Manager, 'emit') as super_emit:
self.pm._handle_emit({'event': 'foo', 'data': [1, 'two']})
super_emit.assert_called_once_with(
'foo',
(1, 'two'),
namespace=None,
room=None,
skip_sid=None,
callback=None,
)
self.pm._handle_emit({
'event': 'foo',
'binary': True,
'data': [
[1, {'_placeholder': True, 'num': 0}, 'three'], 'dHdv'
],
})
super_emit.assert_called_with(
'foo',
(1, b'two', 'three'),
namespace=None,
room=None,
skip_sid=None,
callback=None,
)
def test_handle_emit_with_namespace(self):
with mock.patch.object(manager.Manager, 'emit') as super_emit:
self.pm._handle_emit(

Loading…
Cancel
Save