6 changed files with 324 additions and 1 deletions
@ -0,0 +1,96 @@ |
|||
class Namespace(object): |
|||
"""Base class for class-based namespaces. |
|||
|
|||
A class-based namespace is a class that contains all the event handlers |
|||
for a Socket.IO namespace. The event handlers are methods of the class |
|||
with the prefix ``on_``, such as ``on_connect``, ``on_disconnect``, |
|||
``on_message``, ``on_json``, and so on. |
|||
|
|||
:param namespace: The Socket.IO namespace to be used with all the event |
|||
handlers defined in this class. If this argument is |
|||
omitted, the default namespace is used. |
|||
""" |
|||
def __init__(self, namespace=None): |
|||
self.namespace = namespace or '/' |
|||
self.server = None |
|||
|
|||
def set_server(self, server): |
|||
self.server = server |
|||
|
|||
def trigger_event(self, event, *args): |
|||
handler_name = 'on_' + event |
|||
if hasattr(self, handler_name): |
|||
return getattr(self, handler_name)(*args) |
|||
|
|||
def emit(self, event, data=None, room=None, skip_sid=None, namespace=None, |
|||
callback=None): |
|||
"""Emit a custom event to one or more connected clients. |
|||
|
|||
The only difference with the :func:`socketio.Server.emit` method is |
|||
that when the ``namespace`` argument is not given the namespace |
|||
associated with the class is used. |
|||
""" |
|||
return self.server.emit(event, data=data, room=room, skip_sid=skip_sid, |
|||
namespace=namespace or self.namespace, |
|||
callback=callback) |
|||
|
|||
def send(self, data, room=None, skip_sid=None, namespace=None, |
|||
callback=None): |
|||
"""Send a message to one or more connected clients. |
|||
|
|||
The only difference with the :func:`socketio.Server.send` method is |
|||
that when the ``namespace`` argument is not given the namespace |
|||
associated with the class is used. |
|||
""" |
|||
return self.server.send(data, room=room, skip_sid=skip_sid, |
|||
namespace=namespace or self.namespace, |
|||
callback=callback) |
|||
|
|||
def enter_room(self, sid, room, namespace=None): |
|||
"""Enter a room. |
|||
|
|||
The only difference with the :func:`socketio.Server.enter_room` method |
|||
is that when the ``namespace`` argument is not given the namespace |
|||
associated with the class is used. |
|||
""" |
|||
return self.server.enter_room(sid, room, |
|||
namespace=namespace or self.namespace) |
|||
|
|||
def leave_room(self, sid, room, namespace=None): |
|||
"""Leave a room. |
|||
|
|||
The only difference with the :func:`socketio.Server.leave_room` method |
|||
is that when the ``namespace`` argument is not given the namespace |
|||
associated with the class is used. |
|||
""" |
|||
return self.server.leave_room(sid, room, |
|||
namespace=namespace or self.namespace) |
|||
|
|||
def close_room(self, room, namespace=None): |
|||
"""Close a room. |
|||
|
|||
The only difference with the :func:`socketio.Server.close_room` method |
|||
is that when the ``namespace`` argument is not given the namespace |
|||
associated with the class is used. |
|||
""" |
|||
return self.server.close_room(room, |
|||
namespace=namespace or self.namespace) |
|||
|
|||
def rooms(self, sid, namespace=None): |
|||
"""Return the rooms a client is in. |
|||
|
|||
The only difference with the :func:`socketio.Server.rooms` method is |
|||
that when the ``namespace`` argument is not given the namespace |
|||
associated with the class is used. |
|||
""" |
|||
return self.server.rooms(sid, namespace=namespace or self.namespace) |
|||
|
|||
def disconnect(self, sid, namespace=None): |
|||
"""Disconnect a client. |
|||
|
|||
The only difference with the :func:`socketio.Server.disconnect` method |
|||
is that when the ``namespace`` argument is not given the namespace |
|||
associated with the class is used. |
|||
""" |
|||
return self.server.disconnect(sid, |
|||
namespace=namespace or self.namespace) |
@ -0,0 +1,129 @@ |
|||
import unittest |
|||
import six |
|||
if six.PY3: |
|||
from unittest import mock |
|||
else: |
|||
import mock |
|||
|
|||
from socketio import namespace |
|||
|
|||
|
|||
class TestNamespace(unittest.TestCase): |
|||
def test_connect_event(self): |
|||
result = {} |
|||
|
|||
class MyNamespace(namespace.Namespace): |
|||
def on_connect(self, sid, environ): |
|||
result['result'] = (sid, environ) |
|||
|
|||
ns = MyNamespace('/foo') |
|||
ns.set_server(mock.MagicMock()) |
|||
ns.trigger_event('connect', 'sid', {'foo': 'bar'}) |
|||
self.assertEqual(result['result'], ('sid', {'foo': 'bar'})) |
|||
|
|||
def test_disconnect_event(self): |
|||
result = {} |
|||
|
|||
class MyNamespace(namespace.Namespace): |
|||
def on_disconnect(self, sid): |
|||
result['result'] = sid |
|||
|
|||
ns = MyNamespace('/foo') |
|||
ns.set_server(mock.MagicMock()) |
|||
ns.trigger_event('disconnect', 'sid') |
|||
self.assertEqual(result['result'], 'sid') |
|||
|
|||
def test_event(self): |
|||
result = {} |
|||
|
|||
class MyNamespace(namespace.Namespace): |
|||
def on_custom_message(self, sid, data): |
|||
result['result'] = (sid, data) |
|||
|
|||
ns = MyNamespace('/foo') |
|||
ns.set_server(mock.MagicMock()) |
|||
ns.trigger_event('custom_message', 'sid', {'data': 'data'}) |
|||
self.assertEqual(result['result'], ('sid', {'data': 'data'})) |
|||
|
|||
def test_event_not_found(self): |
|||
result = {} |
|||
|
|||
class MyNamespace(namespace.Namespace): |
|||
def on_custom_message(self, sid, data): |
|||
result['result'] = (sid, data) |
|||
|
|||
ns = MyNamespace('/foo') |
|||
ns.set_server(mock.MagicMock()) |
|||
ns.trigger_event('another_custom_message', 'sid', {'data': 'data'}) |
|||
self.assertEqual(result, {}) |
|||
|
|||
def test_emit(self): |
|||
ns = namespace.Namespace('/foo') |
|||
ns.set_server(mock.MagicMock()) |
|||
ns.emit('ev', data='data', room='room', skip_sid='skip', |
|||
callback='cb') |
|||
ns.server.emit.assert_called_with( |
|||
'ev', data='data', room='room', skip_sid='skip', namespace='/foo', |
|||
callback='cb') |
|||
ns.emit('ev', data='data', room='room', skip_sid='skip', |
|||
namespace='/bar', callback='cb') |
|||
ns.server.emit.assert_called_with( |
|||
'ev', data='data', room='room', skip_sid='skip', namespace='/bar', |
|||
callback='cb') |
|||
|
|||
def test_send(self): |
|||
ns = namespace.Namespace('/foo') |
|||
ns.set_server(mock.MagicMock()) |
|||
ns.send(data='data', room='room', skip_sid='skip', callback='cb') |
|||
ns.server.send.assert_called_with( |
|||
'data', room='room', skip_sid='skip', namespace='/foo', |
|||
callback='cb') |
|||
ns.send(data='data', room='room', skip_sid='skip', namespace='/bar', |
|||
callback='cb') |
|||
ns.server.send.assert_called_with( |
|||
'data', room='room', skip_sid='skip', namespace='/bar', |
|||
callback='cb') |
|||
|
|||
def test_enter_room(self): |
|||
ns = namespace.Namespace('/foo') |
|||
ns.set_server(mock.MagicMock()) |
|||
ns.enter_room('sid', 'room') |
|||
ns.server.enter_room.assert_called_with('sid', 'room', |
|||
namespace='/foo') |
|||
ns.enter_room('sid', 'room', namespace='/bar') |
|||
ns.server.enter_room.assert_called_with('sid', 'room', |
|||
namespace='/bar') |
|||
|
|||
def test_leave_room(self): |
|||
ns = namespace.Namespace('/foo') |
|||
ns.set_server(mock.MagicMock()) |
|||
ns.leave_room('sid', 'room') |
|||
ns.server.leave_room.assert_called_with('sid', 'room', |
|||
namespace='/foo') |
|||
ns.leave_room('sid', 'room', namespace='/bar') |
|||
ns.server.leave_room.assert_called_with('sid', 'room', |
|||
namespace='/bar') |
|||
|
|||
def test_close_room(self): |
|||
ns = namespace.Namespace('/foo') |
|||
ns.set_server(mock.MagicMock()) |
|||
ns.close_room('room') |
|||
ns.server.close_room.assert_called_with('room', namespace='/foo') |
|||
ns.close_room('room', namespace='/bar') |
|||
ns.server.close_room.assert_called_with('room', namespace='/bar') |
|||
|
|||
def test_rooms(self): |
|||
ns = namespace.Namespace('/foo') |
|||
ns.set_server(mock.MagicMock()) |
|||
ns.rooms('sid') |
|||
ns.server.rooms.assert_called_with('sid', namespace='/foo') |
|||
ns.rooms('sid', namespace='/bar') |
|||
ns.server.rooms.assert_called_with('sid', namespace='/bar') |
|||
|
|||
def test_disconnect(self): |
|||
ns = namespace.Namespace('/foo') |
|||
ns.set_server(mock.MagicMock()) |
|||
ns.disconnect('sid') |
|||
ns.server.disconnect.assert_called_with('sid', namespace='/foo') |
|||
ns.disconnect('sid', namespace='/bar') |
|||
ns.server.disconnect.assert_called_with('sid', namespace='/bar') |
Loading…
Reference in new issue