diff --git a/src/socketio/asyncio_namespace.py b/src/socketio/asyncio_namespace.py index eba8838..1ab38a9 100644 --- a/src/socketio/asyncio_namespace.py +++ b/src/socketio/asyncio_namespace.py @@ -71,6 +71,18 @@ class AsyncNamespace(namespace.Namespace): namespace=namespace or self.namespace, callback=callback) + async def call(self, event, data=None, to=None, sid=None, namespace=None, + timeout=None): + """Emit a custom event to a client and wait for the response. + + The only difference with the :func:`socketio.Server.call` method is + that when the ``namespace`` argument is not given the namespace + associated with the class is used. + """ + return await self.server.call(event, data=data, to=to, sid=sid, + namespace=namespace or self.namespace, + timeout=timeout) + async def close_room(self, room, namespace=None): """Close a room. @@ -193,6 +205,17 @@ class AsyncClientNamespace(namespace.ClientNamespace): namespace=namespace or self.namespace, callback=callback) + async def call(self, event, data=None, namespace=None, timeout=None): + """Emit a custom event to the server and wait for the response. + + The only difference with the :func:`socketio.Client.call` method is + that when the ``namespace`` argument is not given the namespace + associated with the class is used. + """ + return await self.client.call(event, data=data, + namespace=namespace or self.namespace, + timeout=timeout) + async def disconnect(self): """Disconnect a client. diff --git a/src/socketio/namespace.py b/src/socketio/namespace.py index 4e1ec79..0d9dd98 100644 --- a/src/socketio/namespace.py +++ b/src/socketio/namespace.py @@ -62,6 +62,18 @@ class Namespace(BaseNamespace): namespace=namespace or self.namespace, callback=callback) + def call(self, event, data=None, to=None, sid=None, namespace=None, + timeout=None): + """Emit a custom event to a client and wait for the response. + + The only difference with the :func:`socketio.Server.call` method is + that when the ``namespace`` argument is not given the namespace + associated with the class is used. + """ + return self.server.call(event, data=data, to=to, sid=sid, + namespace=namespace or self.namespace, + timeout=timeout) + def enter_room(self, sid, room, namespace=None): """Enter a room. @@ -171,8 +183,7 @@ class ClientNamespace(BaseNamespace): namespace=namespace or self.namespace, callback=callback) - def send(self, data, room=None, skip_sid=None, namespace=None, - callback=None): + def send(self, data, room=None, namespace=None, callback=None): """Send a message to the server. The only difference with the :func:`socketio.Client.send` method is @@ -182,6 +193,17 @@ class ClientNamespace(BaseNamespace): return self.client.send(data, namespace=namespace or self.namespace, callback=callback) + def call(self, event, data=None, namespace=None, timeout=None): + """Emit a custom event to the server and wait for the response. + + The only difference with the :func:`socketio.Client.call` method is + that when the ``namespace`` argument is not given the namespace + associated with the class is used. + """ + return self.client.call(event, data=data, + namespace=namespace or self.namespace, + timeout=timeout) + def disconnect(self): """Disconnect from the server. diff --git a/tests/asyncio/test_asyncio_namespace.py b/tests/asyncio/test_asyncio_namespace.py index aa73f5f..2bf2ffd 100644 --- a/tests/asyncio/test_asyncio_namespace.py +++ b/tests/asyncio/test_asyncio_namespace.py @@ -157,6 +157,31 @@ class TestAsyncNamespace(unittest.TestCase): callback='cb', ) + def test_call(self): + ns = asyncio_namespace.AsyncNamespace('/foo') + mock_server = mock.MagicMock() + mock_server.call = AsyncMock() + ns._set_server(mock_server) + _run(ns.call('ev', data='data', to='sid')) + ns.server.call.mock.assert_called_with( + 'ev', + data='data', + to='sid', + sid=None, + namespace='/foo', + timeout=None, + ) + _run(ns.call('ev', data='data', sid='sid', namespace='/bar', + timeout=45)) + ns.server.call.mock.assert_called_with( + 'ev', + data='data', + to=None, + sid='sid', + namespace='/bar', + timeout=45, + ) + def test_enter_room(self): ns = asyncio_namespace.AsyncNamespace('/foo') ns._set_server(mock.MagicMock()) @@ -298,6 +323,20 @@ class TestAsyncNamespace(unittest.TestCase): 'data', namespace='/bar', callback='cb' ) + def test_call_client(self): + ns = asyncio_namespace.AsyncClientNamespace('/foo') + mock_client = mock.MagicMock() + mock_client.call = AsyncMock() + ns._set_client(mock_client) + _run(ns.call('ev', data='data')) + ns.client.call.mock.assert_called_with( + 'ev', data='data', namespace='/foo', timeout=None + ) + _run(ns.call('ev', data='data', namespace='/bar', timeout=45)) + ns.client.call.mock.assert_called_with( + 'ev', data='data', namespace='/bar', timeout=45 + ) + def test_disconnect_client(self): ns = asyncio_namespace.AsyncClientNamespace('/foo') mock_client = mock.MagicMock() diff --git a/tests/common/test_namespace.py b/tests/common/test_namespace.py index e42f864..f096111 100644 --- a/tests/common/test_namespace.py +++ b/tests/common/test_namespace.py @@ -112,6 +112,34 @@ class TestNamespace(unittest.TestCase): callback='cb', ) + def test_call(self): + ns = namespace.Namespace('/foo') + ns._set_server(mock.MagicMock()) + ns.call('ev', data='data', to='sid') + ns.server.call.assert_called_with( + 'ev', + data='data', + to='sid', + sid=None, + namespace='/foo', + timeout=None, + ) + ns.call( + 'ev', + data='data', + sid='sid', + namespace='/bar', + timeout=45, + ) + ns.server.call.assert_called_with( + 'ev', + data='data', + to=None, + sid='sid', + namespace='/bar', + timeout=45, + ) + def test_enter_room(self): ns = namespace.Namespace('/foo') ns._set_server(mock.MagicMock()) @@ -204,6 +232,17 @@ class TestNamespace(unittest.TestCase): 'data', namespace='/bar', callback='cb' ) + def test_call_client(self): + ns = namespace.ClientNamespace('/foo') + ns._set_client(mock.MagicMock()) + ns.call('ev', data='data') + ns.client.call.assert_called_with( + 'ev', data='data', namespace='/foo', timeout=None) + ns.call('ev', data='data', namespace='/bar', timeout=45) + ns.client.call.assert_called_with( + 'ev', data='data', namespace='/bar', timeout=45 + ) + def test_disconnect_client(self): ns = namespace.ClientNamespace('/foo') ns._set_client(mock.MagicMock())