1class BaseNamespace(object):
2    def __init__(self, namespace=None):
3        self.namespace = namespace or '/'
4
5    def is_asyncio_based(self):
6        return False
7
8    def trigger_event(self, event, *args):
9        """Dispatch an event to the proper handler method.
10
11        In the most common usage, this method is not overloaded by subclasses,
12        as it performs the routing of events to methods. However, this
13        method can be overridden if special dispatching rules are needed, or if
14        having a single method that catches all events is desired.
15        """
16        handler_name = 'on_' + event
17        if hasattr(self, handler_name):
18            return getattr(self, handler_name)(*args)
19
20
21class Namespace(BaseNamespace):
22    """Base class for server-side class-based namespaces.
23
24    A class-based namespace is a class that contains all the event handlers
25    for a Socket.IO namespace. The event handlers are methods of the class
26    with the prefix ``on_``, such as ``on_connect``, ``on_disconnect``,
27    ``on_message``, ``on_json``, and so on.
28
29    :param namespace: The Socket.IO namespace to be used with all the event
30                      handlers defined in this class. If this argument is
31                      omitted, the default namespace is used.
32    """
33    def __init__(self, namespace=None):
34        super(Namespace, self).__init__(namespace=namespace)
35        self.server = None
36
37    def _set_server(self, server):
38        self.server = server
39
40    def emit(self, event, data=None, room=None, skip_sid=None, namespace=None,
41             callback=None):
42        """Emit a custom event to one or more connected clients.
43
44        The only difference with the :func:`socketio.Server.emit` method is
45        that when the ``namespace`` argument is not given the namespace
46        associated with the class is used.
47        """
48        return self.server.emit(event, data=data, room=room, skip_sid=skip_sid,
49                                namespace=namespace or self.namespace,
50                                callback=callback)
51
52    def send(self, data, room=None, skip_sid=None, namespace=None,
53             callback=None):
54        """Send a message to one or more connected clients.
55
56        The only difference with the :func:`socketio.Server.send` method is
57        that when the ``namespace`` argument is not given the namespace
58        associated with the class is used.
59        """
60        return self.server.send(data, room=room, skip_sid=skip_sid,
61                                namespace=namespace or self.namespace,
62                                callback=callback)
63
64    def enter_room(self, sid, room, namespace=None):
65        """Enter a room.
66
67        The only difference with the :func:`socketio.Server.enter_room` method
68        is that when the ``namespace`` argument is not given the namespace
69        associated with the class is used.
70        """
71        return self.server.enter_room(sid, room,
72                                      namespace=namespace or self.namespace)
73
74    def leave_room(self, sid, room, namespace=None):
75        """Leave a room.
76
77        The only difference with the :func:`socketio.Server.leave_room` method
78        is that when the ``namespace`` argument is not given the namespace
79        associated with the class is used.
80        """
81        return self.server.leave_room(sid, room,
82                                      namespace=namespace or self.namespace)
83
84    def close_room(self, room, namespace=None):
85        """Close a room.
86
87        The only difference with the :func:`socketio.Server.close_room` method
88        is that when the ``namespace`` argument is not given the namespace
89        associated with the class is used.
90        """
91        return self.server.close_room(room,
92                                      namespace=namespace or self.namespace)
93
94    def rooms(self, sid, namespace=None):
95        """Return the rooms a client is in.
96
97        The only difference with the :func:`socketio.Server.rooms` method is
98        that when the ``namespace`` argument is not given the namespace
99        associated with the class is used.
100        """
101        return self.server.rooms(sid, namespace=namespace or self.namespace)
102
103    def get_session(self, sid, namespace=None):
104        """Return the user session for a client.
105
106        The only difference with the :func:`socketio.Server.get_session`
107        method is that when the ``namespace`` argument is not given the
108        namespace associated with the class is used.
109        """
110        return self.server.get_session(
111            sid, namespace=namespace or self.namespace)
112
113    def save_session(self, sid, session, namespace=None):
114        """Store the user session for a client.
115
116        The only difference with the :func:`socketio.Server.save_session`
117        method is that when the ``namespace`` argument is not given the
118        namespace associated with the class is used.
119        """
120        return self.server.save_session(
121            sid, session, namespace=namespace or self.namespace)
122
123    def session(self, sid, namespace=None):
124        """Return the user session for a client with context manager syntax.
125
126        The only difference with the :func:`socketio.Server.session` method is
127        that when the ``namespace`` argument is not given the namespace
128        associated with the class is used.
129        """
130        return self.server.session(sid, namespace=namespace or self.namespace)
131
132    def disconnect(self, sid, namespace=None):
133        """Disconnect a client.
134
135        The only difference with the :func:`socketio.Server.disconnect` method
136        is that when the ``namespace`` argument is not given the namespace
137        associated with the class is used.
138        """
139        return self.server.disconnect(sid,
140                                      namespace=namespace or self.namespace)
141
142
143class ClientNamespace(BaseNamespace):
144    """Base class for client-side class-based namespaces.
145
146    A class-based namespace is a class that contains all the event handlers
147    for a Socket.IO namespace. The event handlers are methods of the class
148    with the prefix ``on_``, such as ``on_connect``, ``on_disconnect``,
149    ``on_message``, ``on_json``, and so on.
150
151    :param namespace: The Socket.IO namespace to be used with all the event
152                      handlers defined in this class. If this argument is
153                      omitted, the default namespace is used.
154    """
155    def __init__(self, namespace=None):
156        super(ClientNamespace, self).__init__(namespace=namespace)
157        self.client = None
158
159    def _set_client(self, client):
160        self.client = client
161
162    def emit(self, event, data=None, namespace=None, callback=None):
163        """Emit a custom event to the server.
164
165        The only difference with the :func:`socketio.Client.emit` method is
166        that when the ``namespace`` argument is not given the namespace
167        associated with the class is used.
168        """
169        return self.client.emit(event, data=data,
170                                namespace=namespace or self.namespace,
171                                callback=callback)
172
173    def send(self, data, room=None, skip_sid=None, namespace=None,
174             callback=None):
175        """Send a message to the server.
176
177        The only difference with the :func:`socketio.Client.send` method is
178        that when the ``namespace`` argument is not given the namespace
179        associated with the class is used.
180        """
181        return self.client.send(data, namespace=namespace or self.namespace,
182                                callback=callback)
183
184    def disconnect(self):
185        """Disconnect from the server.
186
187        The only difference with the :func:`socketio.Client.disconnect` method
188        is that when the ``namespace`` argument is not given the namespace
189        associated with the class is used.
190        """
191        return self.client.disconnect()
192