Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
base_server.py264 linesDownload Raw Back to socketio
1import logging2 3from . import manager4from . import base_namespace5from . import packet6 7default_logger = logging.getLogger('socketio.server')8 9 10class BaseServer:11    reserved_events = ['connect', 'disconnect']12 13    def __init__(self, client_manager=None, logger=False, serializer='default',14                 json=None, async_handlers=True, always_connect=False,15                 namespaces=None, **kwargs):16        engineio_options = kwargs17        engineio_logger = engineio_options.pop('engineio_logger', None)18        if engineio_logger is not None:19            engineio_options['logger'] = engineio_logger20        if serializer == 'default':21            self.packet_class = packet.Packet22        elif serializer == 'msgpack':23            from . import msgpack_packet24            self.packet_class = msgpack_packet.MsgPackPacket25        else:26            self.packet_class = serializer27        if json is not None:28            self.packet_class.json = json29            engineio_options['json'] = json30        engineio_options['async_handlers'] = False31        self.eio = self._engineio_server_class()(**engineio_options)32        self.eio.on('connect', self._handle_eio_connect)33        self.eio.on('message', self._handle_eio_message)34        self.eio.on('disconnect', self._handle_eio_disconnect)35 36        self.environ = {}37        self.handlers = {}38        self.namespace_handlers = {}39        self.not_handled = object()40 41        self._binary_packet = {}42 43        if not isinstance(logger, bool):44            self.logger = logger45        else:46            self.logger = default_logger47            if self.logger.level == logging.NOTSET:48                if logger:49                    self.logger.setLevel(logging.INFO)50                else:51                    self.logger.setLevel(logging.ERROR)52                self.logger.addHandler(logging.StreamHandler())53 54        if client_manager is None:55            client_manager = manager.Manager()56        self.manager = client_manager57        self.manager.set_server(self)58        self.manager_initialized = False59 60        self.async_handlers = async_handlers61        self.always_connect = always_connect62        self.namespaces = namespaces or ['/']63 64        self.async_mode = self.eio.async_mode65 66    def is_asyncio_based(self):67        return False68 69    def on(self, event, handler=None, namespace=None):70        """Register an event handler.71 72        :param event: The event name. It can be any string. The event names73                      ``'connect'``, ``'message'`` and ``'disconnect'`` are74                      reserved and should not be used. The ``'*'`` event name75                      can be used to define a catch-all event handler.76        :param handler: The function that should be invoked to handle the77                        event. When this parameter is not given, the method78                        acts as a decorator for the handler function.79        :param namespace: The Socket.IO namespace for the event. If this80                          argument is omitted the handler is associated with81                          the default namespace. A catch-all namespace can be82                          defined by passing ``'*'`` as the namespace.83 84        Example usage::85 86            # as a decorator:87            @sio.on('connect', namespace='/chat')88            def connect_handler(sid, environ):89                print('Connection request')90                if environ['REMOTE_ADDR'] in blacklisted:91                    return False  # reject92 93            # as a method:94            def message_handler(sid, msg):95                print('Received message: ', msg)96                sio.send(sid, 'response')97            socket_io.on('message', namespace='/chat', handler=message_handler)98 99        The arguments passed to the handler function depend on the event type:100 101        - The ``'connect'`` event handler receives the ``sid`` (session ID) for102          the client and the WSGI environment dictionary as arguments.103        - The ``'disconnect'`` handler receives the ``sid`` for the client as104          only argument.105        - The ``'message'`` handler and handlers for custom event names receive106          the ``sid`` for the client and the message payload as arguments. Any107          values returned from a message handler will be passed to the client's108          acknowledgement callback function if it exists.109        - A catch-all event handler receives the event name as first argument,110          followed by any arguments specific to the event.111        - A catch-all namespace event handler receives the namespace as first112          argument, followed by any arguments specific to the event.113        - A combined catch-all namespace and catch-all event handler receives114          the event name as first argument and the namespace as second115          argument, followed by any arguments specific to the event.116        """117        namespace = namespace or '/'118 119        def set_handler(handler):120            if namespace not in self.handlers:121                self.handlers[namespace] = {}122            self.handlers[namespace][event] = handler123            return handler124 125        if handler is None:126            return set_handler127        set_handler(handler)128 129    def event(self, *args, **kwargs):130        """Decorator to register an event handler.131 132        This is a simplified version of the ``on()`` method that takes the133        event name from the decorated function.134 135        Example usage::136 137            @sio.event138            def my_event(data):139                print('Received data: ', data)140 141        The above example is equivalent to::142 143            @sio.on('my_event')144            def my_event(data):145                print('Received data: ', data)146 147        A custom namespace can be given as an argument to the decorator::148 149            @sio.event(namespace='/test')150            def my_event(data):151                print('Received data: ', data)152        """153        if len(args) == 1 and len(kwargs) == 0 and callable(args[0]):154            # the decorator was invoked without arguments155            # args[0] is the decorated function156            return self.on(args[0].__name__)(args[0])157        else:158            # the decorator was invoked with arguments159            def set_handler(handler):160                return self.on(handler.__name__, *args, **kwargs)(handler)161 162            return set_handler163 164    def register_namespace(self, namespace_handler):165        """Register a namespace handler object.166 167        :param namespace_handler: An instance of a :class:`Namespace`168                                  subclass that handles all the event traffic169                                  for a namespace.170        """171        if not isinstance(namespace_handler,172                          base_namespace.BaseServerNamespace):173            raise ValueError('Not a namespace instance')174        if self.is_asyncio_based() != namespace_handler.is_asyncio_based():175            raise ValueError('Not a valid namespace class for this server')176        namespace_handler._set_server(self)177        self.namespace_handlers[namespace_handler.namespace] = \178            namespace_handler179 180    def rooms(self, sid, namespace=None):181        """Return the rooms a client is in.182 183        :param sid: Session ID of the client.184        :param namespace: The Socket.IO namespace for the event. If this185                          argument is omitted the default namespace is used.186        """187        namespace = namespace or '/'188        return self.manager.get_rooms(sid, namespace)189 190    def transport(self, sid, namespace=None):191        """Return the name of the transport used by the client.192 193        The two possible values returned by this function are ``'polling'``194        and ``'websocket'``.195 196        :param sid: The session of the client.197        :param namespace: The Socket.IO namespace. If this argument is omitted198                          the default namespace is used.199        """200        eio_sid = self.manager.eio_sid_from_sid(sid, namespace or '/')201        return self.eio.transport(eio_sid)202 203    def get_environ(self, sid, namespace=None):204        """Return the WSGI environ dictionary for a client.205 206        :param sid: The session of the client.207        :param namespace: The Socket.IO namespace. If this argument is omitted208                          the default namespace is used.209        """210        eio_sid = self.manager.eio_sid_from_sid(sid, namespace or '/')211        return self.environ.get(eio_sid)212 213    def _get_event_handler(self, event, namespace, args):214        # Return the appropriate application event handler215        #216        # Resolution priority:217        # - self.handlers[namespace][event]218        # - self.handlers[namespace]["*"]219        # - self.handlers["*"][event]220        # - self.handlers["*"]["*"]221        handler = None222        if namespace in self.handlers:223            if event in self.handlers[namespace]:224                handler = self.handlers[namespace][event]225            elif event not in self.reserved_events and \226                    '*' in self.handlers[namespace]:227                handler = self.handlers[namespace]['*']228                args = (event, *args)229        if handler is None and '*' in self.handlers:230            if event in self.handlers['*']:231                handler = self.handlers['*'][event]232                args = (namespace, *args)233            elif event not in self.reserved_events and \234                    '*' in self.handlers['*']:235                handler = self.handlers['*']['*']236                args = (event, namespace, *args)237        return handler, args238 239    def _get_namespace_handler(self, namespace, args):240        # Return the appropriate application event handler.241        #242        # Resolution priority:243        # - self.namespace_handlers[namespace]244        # - self.namespace_handlers["*"]245        handler = None246        if namespace in self.namespace_handlers:247            handler = self.namespace_handlers[namespace]248        if handler is None and '*' in self.namespace_handlers:249            handler = self.namespace_handlers['*']250            args = (namespace, *args)251        return handler, args252 253    def _handle_eio_connect(self):  # pragma: no cover254        raise NotImplementedError()255 256    def _handle_eio_message(self, data):  # pragma: no cover257        raise NotImplementedError()258 259    def _handle_eio_disconnect(self):  # pragma: no cover260        raise NotImplementedError()261 262    def _engineio_server_class(self):  # pragma: no cover263        raise NotImplementedError('Must be implemented in subclasses')264 
codekingpro/portable-devtools · Team Ai