Skip to content

Commit

Permalink
close_room() function (fixes #84)
Browse files Browse the repository at this point in the history
  • Loading branch information
miguelgrinberg committed Jan 5, 2015
1 parent d8c7316 commit 558297d
Show file tree
Hide file tree
Showing 5 changed files with 113 additions and 13 deletions.
1 change: 1 addition & 0 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -311,4 +311,5 @@ API Reference
.. autofunction:: send
.. autofunction:: join_room
.. autofunction:: leave_room
.. autofunction:: close_room
.. autofunction:: disconnect
20 changes: 19 additions & 1 deletion example/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
import time
from threading import Thread
from flask import Flask, render_template, session, request
from flask.ext.socketio import SocketIO, emit, join_room, leave_room
from flask.ext.socketio import SocketIO, emit, join_room, leave_room, \
close_room, disconnect

app = Flask(__name__)
app.debug = True
Expand Down Expand Up @@ -66,6 +67,15 @@ def leave(message):
'count': session['receive_count']})


@socketio.on('close room', namespace='/test')
def close(message):
session['receive_count'] = session.get('receive_count', 0) + 1
emit('my response', {'data': 'Room ' + message['room'] + ' is closing.',
'count': session['receive_count']},
room=message['room'])
close_room(message['room'])


@socketio.on('my room event', namespace='/test')
def send_room_message(message):
session['receive_count'] = session.get('receive_count', 0) + 1
Expand All @@ -74,6 +84,14 @@ def send_room_message(message):
room=message['room'])


@socketio.on('disconnect request', namespace='/test')
def disconnect_request():
session['receive_count'] = session.get('receive_count', 0) + 1
emit('my response',
{'data': 'Disconnected!', 'count': session['receive_count']})
disconnect()


@socketio.on('connect', namespace='/test')
def test_connect():
emit('my response', {'data': 'Connected', 'count': 0})
Expand Down
25 changes: 20 additions & 5 deletions example/templates/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -43,33 +43,48 @@
socket.emit('my room event', {room: $('#room_name').val(), data: $('#room_data').val()});
return false;
});
$('form#close').submit(function(event) {
socket.emit('close room', {room: $('#close_room').val()});
return false;
});
$('form#disconnect').submit(function(event) {
socket.emit('disconnect request');
return false;
});
});
</script>
</head>
<body>
<h1>Flask-SocketIO Test</h1>
<h2>Send:</h2>
<form id="emit" method='POST' action='#'>
<form id="emit" method="POST" action='#'>
<input type="text" name="emit_data" id="emit_data" placeholder="Message">
<input type="submit" value="Echo"></div>
</form>
<form id="broadcast" method='POST' action='#'>
<form id="broadcast" method="POST" action='#'>
<input type="text" name="broadcast_data" id="broadcast_data" placeholder="Message">
<input type="submit" value="Broadcast">
</form>
<form id="join" method='POST' action='#'>
<form id="join" method="POST" action='#'>
<input type="text" name="join_room" id="join_room" placeholder="Room Name">
<input type="submit" value="Join Room">
</form>
<form id="leave" method='POST' action='#'>
<form id="leave" method="POST" action='#'>
<input type="text" name="leave_room" id="leave_room" placeholder="Room Name">
<input type="submit" value="Leave Room">
</form>
<form id="send_room" method='POST' action='#'>
<form id="send_room" method="POST" action='#'>
<input type="text" name="room_name" id="room_name" placeholder="Room Name">
<input type="text" name="room_data" id="room_data" placeholder="Message">
<input type="submit" value="Send to Room">
</form>
<form id="close" method="POST" action="#">
<input type="text" name="close_room" id="close_room" placeholder="Room Name">
<input type="submit" value="Close Room">
</form>
<form id="disconnect" method="POST" action="#">
<input type="submit" value="Disconnect">
</form>
<h2>Receive:</h2>
<div id="log"></div>
</body>
Expand Down
46 changes: 44 additions & 2 deletions flask_socketio/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,9 @@ def leave_room(self, room):
if self.socketio._leave_room(self, room):
self.rooms.remove(room)

def close_room(self, room):
self.socketio._close_room(self, room)

def recv_connect(self):
if self.socketio.server is None:
self.socketio.server = self.environ['socketio'].server
Expand All @@ -91,8 +94,7 @@ def recv_disconnect(self):
self.socketio.server = self.environ['socketio'].server
app = self.request
self.socketio._dispatch_message(app, self, 'disconnect')
for room in self.rooms.copy():
self.leave_room(room)
self.socketio._leave_all_rooms(self)
return super(GenericNamespace, self).recv_disconnect()

def recv_message(self, data):
Expand Down Expand Up @@ -135,6 +137,10 @@ def send(self, message, json=False, ns_name=None, callback=None,
json,
callback)

def disconnect(self, silent=False):
self.socketio._leave_all_rooms(self)
return super(GenericNamespace, self).disconnect(silent)

namespaces = dict((ns_name, GenericNamespace)
for ns_name in self.messages)
return namespaces
Expand Down Expand Up @@ -176,6 +182,14 @@ def _leave_room(self, namespace, room):
return True
return False

def _close_room(self, namespace, room):
self.close_room(room, namespace.ns_name)

def _leave_all_rooms(self, namespace):
if namespace.ns_name in self.rooms:
for room in self.rooms[namespace.ns_name].copy():
self._leave_room(namespace, room)

def _on_message(self, message, handler, namespace=''):
if namespace not in self.messages:
self.messages[namespace] = {}
Expand Down Expand Up @@ -315,6 +329,22 @@ def send(self, message, json=False, namespace=None, room=None):
if socket.active_ns.get(ns_name):
socket[ns_name].base_send(message, json)

def close_room(self, room, namespace=''):
"""Close a room.
This function removes any users that are in the given room and then
deletes the room from the server. This function can be used outside
of a SocketIO event context.
:param room: The name of the room to close.
:param namespace: The namespace under which the room exists. Defaults
to the global namespace.
"""
if namespace in self.rooms:
if room in self.rooms[namespace]:
for ns in self.rooms[namespace][room].copy():
self._leave_room(ns, room)

def run(self, app, host=None, port=None, **kwargs):
"""Run the SocketIO web server.
Expand Down Expand Up @@ -474,6 +504,18 @@ def on_leave(data):
return request.namespace.leave_room(room)


def close_room(room):
"""Close a room.
This function removes any users that are in the given room and then deletes
the room from the server. This is a function that can only be called from
a SocketIO event handler.
:param room: The name of the room to close.
"""
return request.namespace.close_room(room)


def disconnect(silent=False):
"""Disconnect the client.
Expand Down
34 changes: 29 additions & 5 deletions test_socketio.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,84 +15,103 @@
socketio = SocketIO(app)
disconnected = None


@socketio.on('connect')
def on_connect():
send('connected')
session['a'] = 'b'


@socketio.on('disconnect')
def on_connect():
def on_disconnect():
global disconnected
disconnected = '/'


@socketio.on('connect', namespace='/test')
def on_connect_test():
send('connected-test')


@socketio.on('disconnect', namespace='/test')
def on_disconnect_test():
global disconnected
disconnected = '/test'


@socketio.on('message')
def on_message(message):
send(message)


@socketio.on('json')
def on_json(data):
send(data, json=True, broadcast=True)


@socketio.on('message', namespace='/test')
def on_message_test(message):
send(message)


@socketio.on('json', namespace='/test')
def on_json_test(data):
send(data, json=True, namespace='/test')


@socketio.on('my custom event')
def on_custom_event(data):
emit('my custom response', data)


@socketio.on('my custom namespace event', namespace='/test')
def on_custom_event_test(data):
emit('my custom namespace response', data, namespace='/test')


@socketio.on('my custom broadcast event')
def on_custom_event_broadcast(data):
emit('my custom response', data, broadcast=True)


@socketio.on('my custom broadcast namespace event', namespace='/test')
def on_custom_event_broadcast_test(data):
emit('my custom namespace response', data, namespace='/test',
broadcast=True)


@socketio.on('join room')
def on_join_room(data):
join_room(data['room'])


@socketio.on('leave room')
def on_leave_room(data):
leave_room(data['room'])


@socketio.on('join room', namespace='/test')
def on_join_room(data):
def on_join_room_namespace(data):
join_room(data['room'])


@socketio.on('leave room', namespace='/test')
def on_leave_room(data):
def on_leave_room_namespace(data):
leave_room(data['room'])


@socketio.on('my room event')
def on_room_event(data):
room = data.pop('room')
emit('my room response', data, room=room)


@socketio.on('my room namespace event', namespace='/test')
def on_room_namespace_event(data):
room = data.pop('room')
send('room message', room=room)


@socketio.on_error()
def error_handler(value):
if isinstance(value, AssertionError):
Expand All @@ -101,10 +120,12 @@ def error_handler(value):
else:
raise value


@socketio.on('error testing')
def raise_error(data):
raise AssertionError()


@socketio.on_error('/test')
def error_handler_namespace(value):
if isinstance(value, AssertionError):
Expand All @@ -113,17 +134,20 @@ def error_handler_namespace(value):
else:
raise value


@socketio.on("error testing", namespace='/test')
def raise_error_namespace(data):
raise AssertionError()


@socketio.on_error_default
def error_handler_default(value):
if isinstance(value, AssertionError):
global error_testing_default
error_testing_default = True
else:
raise exception, value, traceback
raise value


@socketio.on("error testing", namespace='/unused_namespace')
def raise_error_default(data):
Expand Down Expand Up @@ -306,7 +330,7 @@ def test_room(self):
self.assertTrue(received[0]['name'] == 'message')
self.assertTrue(received[0]['args'] == 'room message')
self.assertTrue(len(socketio.rooms) == 1)
client3.disconnect('/test')
socketio.close_room('one', namespace='/test')
self.assertTrue(len(socketio.rooms) == 0)

def test_error_handling(self):
Expand Down

0 comments on commit 558297d

Please sign in to comment.