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