Browse Source

Implemented dynamic event -> handler mapping in Namespace class.

pull/43/merge^2
Robert Schindler 9 years ago
parent
commit
8ab72d0eab
  1. 15
      socketio/namespace.py
  2. 22
      socketio/server.py
  3. 9
      tests/test_server.py

15
socketio/namespace.py

@ -54,20 +54,19 @@ class Namespace(object):
'close_room', 'rooms', 'disconnect'):
setattr(self, func_name, get_wrapped_method(func_name))
def _get_handlers(self):
"""Returns a dict of event names and handlers this namespace
provides."""
handlers = {}
def get_event_handler(self, event_name):
"""Returns the event handler for requested event or ``None``."""
for attr_name in dir(self):
attr = getattr(self, attr_name)
if hasattr(attr, '_event_name'):
event_name = getattr(attr, '_event_name')
_event_name = getattr(attr, '_event_name')
elif attr_name.startswith('on_'):
event_name = attr_name[3:]
_event_name = attr_name[3:]
else:
continue
handlers[event_name] = attr
return handlers
if _event_name == event_name:
return attr
return None
@staticmethod
def event_name(name):

22
socketio/server.py

@ -4,6 +4,7 @@ import engineio
import six
from . import base_manager
from . import namespace as sio_namespace
from . import packet
@ -141,6 +142,10 @@ class Server(object):
namespace = namespace or '/'
def set_handler(handler):
if isinstance(self.handlers.get(namespace),
sio_namespace.Namespace):
raise ValueError('A Namespace object has been registered '
'for this namespace.')
if namespace not in self.handlers:
self.handlers[namespace] = {}
self.handlers[namespace][event] = handler
@ -151,8 +156,8 @@ class Server(object):
set_handler(handler)
def register_namespace(self, name, namespace_class):
"""Register all handlers of the given ``namespace_class`` under the
namespace named by ``name``.
"""Register the given ``namespace_class`` under the namespace named
by ``name``.
:param name: The namespace's name. It can be any string.
:param namespace_class: The sub class of ``Namespace`` to register
@ -163,8 +168,7 @@ class Server(object):
See documentation of ``Namespace`` class for an example.
"""
namespace = namespace_class(name, self)
for event, handler in six.iteritems(namespace._get_handlers()):
self.on(event, handler=handler, namespace=name)
self.handlers[name] = namespace
return namespace
def emit(self, event, data=None, room=None, skip_sid=None, namespace=None,
@ -441,8 +445,14 @@ class Server(object):
def _trigger_event(self, event, namespace, *args):
"""Invoke an application event handler."""
if namespace in self.handlers and event in self.handlers[namespace]:
return self.handlers[namespace][event](*args)
handler = None
ns = self.handlers.get(namespace)
if isinstance(ns, sio_namespace.Namespace):
handler = ns.get_event_handler(event)
elif isinstance(ns, dict):
handler = ns.get(event)
if handler is not None:
return handler(*args)
def _handle_eio_connect(self, sid, environ):
"""Handle the Engine.IO connection event."""

9
tests/test_server.py

@ -48,13 +48,18 @@ class TestServer(unittest.TestCase):
def test_register_namespace(self, eio):
class NS(namespace.Namespace):
def on_foo(self):
def on_foo(self, sid):
self.emit("bar")
@namespace.Namespace.event_name('foo bar')
def abc(self, sid):
self.emit("foo bar")
s = server.Server()
s.register_namespace('/ns', NS)
self.assertIsNotNone(s.handlers['/ns'].get('foo'))
self.assertIsNotNone(s.handlers['/ns'].get_event_handler('foo'))
self.assertIsNotNone(s.handlers['/ns'].get_event_handler('foo bar'))
self.assertIsNone(s.handlers['/ns'].get_event_handler('abc'))
def test_on_bad_event_name(self, eio):
s = server.Server()

Loading…
Cancel
Save