1import asyncio
2
3from .base_manager import BaseManager
4
5
6class AsyncManager(BaseManager):
7    """Manage a client list for an asyncio server."""
8    async def can_disconnect(self, sid, namespace):
9        return self.is_connected(sid, namespace)
10
11    async def emit(self, event, data, namespace, room=None, skip_sid=None,
12                   callback=None, **kwargs):
13        """Emit a message to a single client, a room, or all the clients
14        connected to the namespace.
15
16        Note: this method is a coroutine.
17        """
18        if namespace not in self.rooms or room not in self.rooms[namespace]:
19            return
20        tasks = []
21        if not isinstance(skip_sid, list):
22            skip_sid = [skip_sid]
23        for sid in self.get_participants(namespace, room):
24            if sid not in skip_sid:
25                if callback is not None:
26                    id = self._generate_ack_id(sid, namespace, callback)
27                else:
28                    id = None
29                tasks.append(self.server._emit_internal(sid, event, data,
30                                                        namespace, id))
31        if tasks == []:  # pragma: no cover
32            return
33        await asyncio.wait(tasks)
34
35    async def close_room(self, room, namespace):
36        """Remove all participants from a room.
37
38        Note: this method is a coroutine.
39        """
40        return super().close_room(room, namespace)
41
42    async def trigger_callback(self, sid, namespace, id, data):
43        """Invoke an application callback.
44
45        Note: this method is a coroutine.
46        """
47        callback = None
48        try:
49            callback = self.callbacks[sid][namespace][id]
50        except KeyError:
51            # if we get an unknown callback we just ignore it
52            self._get_logger().warning('Unknown callback received, ignoring.')
53        else:
54            del self.callbacks[sid][namespace][id]
55        if callback is not None:
56            ret = callback(*data)
57            if asyncio.iscoroutine(ret):
58                try:
59                    await ret
60                except asyncio.CancelledError:  # pragma: no cover
61                    pass
62