-
-
Notifications
You must be signed in to change notification settings - Fork 573
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
6abd86f
commit 7bc329a
Showing
6 changed files
with
324 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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') |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters