Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package python-Flask-SocketIO for 
openSUSE:Factory checked in at 2023-06-22 23:26:07
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-Flask-SocketIO (Old)
 and      /work/SRC/openSUSE:Factory/.python-Flask-SocketIO.new.15902 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-Flask-SocketIO"

Thu Jun 22 23:26:07 2023 rev:3 rq:1094493 version:5.3.4

Changes:
--------
--- 
/work/SRC/openSUSE:Factory/python-Flask-SocketIO/python-Flask-SocketIO.changes  
    2021-10-27 22:21:45.147215476 +0200
+++ 
/work/SRC/openSUSE:Factory/.python-Flask-SocketIO.new.15902/python-Flask-SocketIO.changes
   2023-06-22 23:26:31.181981912 +0200
@@ -1,0 +2,11 @@
+Wed Jun 21 21:36:05 UTC 2023 - Matej Cepl <mc...@suse.com>
+
+- Clean up SPEC file, make rpmlint happy.
+
+-------------------------------------------------------------------
+Wed Jun 21 19:56:26 UTC 2023 - Axel Braun <axel.br...@gmx.de>
+
+- update to version 5.3.4
+  * For a full changelog see 
https://github.com/miguelgrinberg/Flask-SocketIO/blob/main/CHANGES.md
+
+-------------------------------------------------------------------

Old:
----
  Flask-SocketIO-5.1.1.tar.gz

New:
----
  Flask-SocketIO-5.3.4.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-Flask-SocketIO.spec ++++++
--- /var/tmp/diff_new_pack.p8vss1/_old  2023-06-22 23:26:31.825985197 +0200
+++ /var/tmp/diff_new_pack.p8vss1/_new  2023-06-22 23:26:31.829985217 +0200
@@ -1,7 +1,7 @@
 #
 # spec file for package python-Flask-SocketIO
 #
-# Copyright (c) 2021 SUSE LLC
+# Copyright (c) 2023 SUSE LLC
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -16,24 +16,24 @@
 #
 
 
-%{?!python_module:%define python_module() python3-%{**}}
 %define skip_python2 1
 Name:           python-Flask-SocketIO
-Version:        5.1.1
+Version:        5.3.4
 Release:        0
-License:        MIT
 Summary:        SocketIO integration for Flask applications
-URL:            http://github.com/miguelgrinberg/Flask-SocketIO/
+License:        MIT
 Group:          Development/Languages/Python
+URL:            https://github.com/miguelgrinberg/Flask-SocketIO/
 Source:         
https://files.pythonhosted.org/packages/source/F/Flask-SocketIO/Flask-SocketIO-%{version}.tar.gz
 Source1:        
https://raw.githubusercontent.com/miguelgrinberg/Flask-SocketIO/v%{version}/test_socketio.py
 BuildRequires:  %{python_module Flask >= 0.9}
+BuildRequires:  %{python_module pip}
 BuildRequires:  %{python_module python-socketio >= 5.0.2}
-BuildRequires:  %{python_module setuptools}
+BuildRequires:  %{python_module redis}
+BuildRequires:  %{python_module wheel}
 BuildRequires:  fdupes
 Requires:       python-Flask >= 0.9
 Requires:       python-python-socketio >= 5.0.2
-
 BuildArch:      noarch
 %python_subpackages
 
@@ -42,13 +42,13 @@
 
 %prep
 %setup -q -n Flask-SocketIO-%{version}
-cp %{S:1} .
+cp %{SOURCE1} .
 
 %build
-%python_build
+%pyproject_wheel
 
 %install
-%python_install
+%pyproject_install
 %python_expand %fdupes %{buildroot}%{$python_sitelib}
 
 %check
@@ -57,6 +57,7 @@
 %files  %{python_files}
 %doc README.md
 %license LICENSE
-%{python_sitelib}/*
+%{python_sitelib}/flask_socketio
+%{python_sitelib}/Flask_SocketIO-%{version}*-info
 
 %changelog

++++++ Flask-SocketIO-5.1.1.tar.gz -> Flask-SocketIO-5.3.4.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Flask-SocketIO-5.1.1/PKG-INFO 
new/Flask-SocketIO-5.3.4/PKG-INFO
--- old/Flask-SocketIO-5.1.1/PKG-INFO   2021-08-02 01:17:34.347939500 +0200
+++ new/Flask-SocketIO-5.3.4/PKG-INFO   2023-05-03 12:34:08.560571200 +0200
@@ -1,13 +1,11 @@
 Metadata-Version: 2.1
 Name: Flask-SocketIO
-Version: 5.1.1
+Version: 5.3.4
 Summary: Socket.IO integration for Flask applications
 Home-page: https://github.com/miguelgrinberg/flask-socketio
 Author: Miguel Grinberg
 Author-email: miguel.grinb...@gmail.com
-License: UNKNOWN
 Project-URL: Bug Tracker, 
https://github.com/miguelgrinberg/flask-socketio/issues
-Platform: UNKNOWN
 Classifier: Environment :: Web Environment
 Classifier: Intended Audience :: Developers
 Classifier: Programming Language :: Python :: 3
@@ -73,5 +71,3 @@
 - [Change 
Log](https://github.com/miguelgrinberg/Flask-SocketIO/blob/main/CHANGES.md)
 - Questions? See the 
[questions](https://stackoverflow.com/questions/tagged/flask-socketio) others 
have asked on Stack Overflow, or 
[ask](https://stackoverflow.com/questions/ask?tags=python+flask-socketio+python-socketio)
 your own question.
 
-
-
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Flask-SocketIO-5.1.1/setup.cfg 
new/Flask-SocketIO-5.3.4/setup.cfg
--- old/Flask-SocketIO-5.1.1/setup.cfg  2021-08-02 01:17:34.348511000 +0200
+++ new/Flask-SocketIO-5.3.4/setup.cfg  2023-05-03 12:34:08.561552300 +0200
@@ -1,6 +1,6 @@
 [metadata]
 name = Flask-SocketIO
-version = 5.1.1
+version = 5.3.4
 author = Miguel Grinberg
 author_email = miguel.grinb...@gmail.com
 description = Socket.IO integration for Flask applications
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/Flask-SocketIO-5.1.1/src/Flask_SocketIO.egg-info/PKG-INFO 
new/Flask-SocketIO-5.3.4/src/Flask_SocketIO.egg-info/PKG-INFO
--- old/Flask-SocketIO-5.1.1/src/Flask_SocketIO.egg-info/PKG-INFO       
2021-08-02 01:17:34.000000000 +0200
+++ new/Flask-SocketIO-5.3.4/src/Flask_SocketIO.egg-info/PKG-INFO       
2023-05-03 12:34:08.000000000 +0200
@@ -1,13 +1,11 @@
 Metadata-Version: 2.1
 Name: Flask-SocketIO
-Version: 5.1.1
+Version: 5.3.4
 Summary: Socket.IO integration for Flask applications
 Home-page: https://github.com/miguelgrinberg/flask-socketio
 Author: Miguel Grinberg
 Author-email: miguel.grinb...@gmail.com
-License: UNKNOWN
 Project-URL: Bug Tracker, 
https://github.com/miguelgrinberg/flask-socketio/issues
-Platform: UNKNOWN
 Classifier: Environment :: Web Environment
 Classifier: Intended Audience :: Developers
 Classifier: Programming Language :: Python :: 3
@@ -73,5 +71,3 @@
 - [Change 
Log](https://github.com/miguelgrinberg/Flask-SocketIO/blob/main/CHANGES.md)
 - Questions? See the 
[questions](https://stackoverflow.com/questions/tagged/flask-socketio) others 
have asked on Stack Overflow, or 
[ask](https://stackoverflow.com/questions/ask?tags=python+flask-socketio+python-socketio)
 your own question.
 
-
-
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Flask-SocketIO-5.1.1/src/flask_socketio/__init__.py 
new/Flask-SocketIO-5.3.4/src/flask_socketio/__init__.py
--- old/Flask-SocketIO-5.1.1/src/flask_socketio/__init__.py     2021-07-18 
18:30:40.000000000 +0200
+++ new/Flask-SocketIO-5.3.4/src/flask_socketio/__init__.py     2023-03-21 
20:59:26.000000000 +0100
@@ -16,7 +16,7 @@
     sys.exit(1)
 
 import flask
-from flask import _request_ctx_stack, has_request_context, json as flask_json
+from flask import has_request_context, json as flask_json
 from flask.sessions import SessionMixin
 import socketio
 from socketio.exceptions import ConnectionRefusedError  # noqa: F401
@@ -197,8 +197,8 @@
         self.manage_session = self.server_options.pop('manage_session',
                                                       self.manage_session)
 
-        if 'client_manager' not in self.server_options:
-            url = self.server_options.pop('message_queue', None)
+        if 'client_manager' not in kwargs:
+            url = self.server_options.get('message_queue', None)
             channel = self.server_options.pop('channel', 'flask-socketio')
             write_only = app is None
             if url:
@@ -248,7 +248,7 @@
             self.server.register_namespace(namespace_handler)
 
         if app is not None:
-            # here we attach the SocketIO middlware to the SocketIO object so
+            # here we attach the SocketIO middleware to the SocketIO object so
             # it can be referenced later if debug middleware needs to be
             # inserted
             self.sockio_mw = _SocketIOMiddleware(self.server, app,
@@ -416,9 +416,9 @@
         :param args: A dictionary with the JSON data to send as payload.
         :param namespace: The namespace under which the message is to be sent.
                           Defaults to the global namespace.
-        :param to: Send the message to all the users in the given room. If
-                   this parameter is not included, the event is sent to all
-                   connected users.
+        :param to: Send the message to all the users in the given room, or to
+                   the user with the given session ID. If this parameter is not
+                   included, the event is sent to all connected users.
         :param include_self: ``True`` to include the sender when broadcasting
                              or addressing a room, or ``False`` to send to
                              everyone but the sender.
@@ -434,7 +434,7 @@
                          only be used when addressing an individual client.
         """
         namespace = kwargs.pop('namespace', '/')
-        to = kwargs.pop('to', kwargs.pop('room', None))
+        to = kwargs.pop('to', None) or kwargs.pop('room', None)
         include_self = kwargs.pop('include_self', True)
         skip_sid = kwargs.pop('skip_sid', None)
         if not include_self and not skip_sid:
@@ -443,13 +443,15 @@
         if callback:
             # wrap the callback so that it sets app app and request contexts
             sid = None
+            original_callback = callback
+            original_namespace = namespace
             if has_request_context():
                 sid = getattr(flask.request, 'sid', None)
-            original_callback = callback
+                original_namespace = getattr(flask.request, 'namespace', None)
 
             def _callback_wrapper(*args):
-                return self._handle_event(original_callback, None, namespace,
-                                          sid, *args)
+                return self._handle_event(original_callback, None,
+                                          original_namespace, sid, *args)
 
             if sid:
                 # the callback wrapper above will install a request context
@@ -460,6 +462,41 @@
         self.server.emit(event, *args, namespace=namespace, to=to,
                          skip_sid=skip_sid, callback=callback, **kwargs)
 
+    def call(self, event, *args, **kwargs):  # pragma: no cover
+        """Emit a SocketIO event and wait for the response.
+
+        This method issues an emit with a callback and waits for the callback
+        to be invoked by the client before returning. If the callback isn’t
+        invoked before the timeout, then a TimeoutError exception is raised. If
+        the Socket.IO connection drops during the wait, this method still waits
+        until the specified timeout. Example::
+
+            def get_status(client, data):
+                status = call('status', {'data': data}, to=client)
+
+        :param event: The name of the user event to emit.
+        :param args: A dictionary with the JSON data to send as payload.
+        :param namespace: The namespace under which the message is to be sent.
+                          Defaults to the global namespace.
+        :param to: The session ID of the recipient client.
+        :param timeout: The waiting timeout. If the timeout is reached before
+                        the client acknowledges the event, then a
+                        ``TimeoutError`` exception is raised. The default is 60
+                        seconds.
+        :param ignore_queue: Only used when a message queue is configured. If
+                             set to ``True``, the event is emitted to the
+                             client directly, without going through the queue.
+                             This is more efficient, but only works when a
+                             single server process is used, or when there is a
+                             single addressee. It is recommended to always
+                             leave this parameter with its default value of
+                             ``False``.
+        """
+        namespace = kwargs.pop('namespace', '/')
+        to = kwargs.pop('to', None) or kwargs.pop('room', None)
+        return self.server.call(event, *args, namespace=namespace, to=to,
+                                **kwargs)
+
     def send(self, data, json=False, namespace=None, to=None,
              callback=None, include_self=True, skip_sid=None, **kwargs):
         """Send a server-generated SocketIO message.
@@ -475,9 +512,9 @@
                      otherwise.
         :param namespace: The namespace under which the message is to be sent.
                           Defaults to the global namespace.
-        :param to: Send the message only to the users in the given room. If
-                   this parameter is not included, the message is sent to all
-                   connected users.
+        :param to: Send the message to all the users in the given room, or to
+                   the user with the given session ID. If this parameter is not
+                   included, the event is sent to all connected users.
         :param include_self: ``True`` to include the sender when broadcasting
                              or addressing a room, or ``False`` to send to
                              everyone but the sender.
@@ -536,6 +573,10 @@
                            Defaults to ``True`` in debug mode, ``False``
                            in normal mode. Unused when the threading async
                            mode is used.
+        :param allow_unsafe_werkzeug: Set to ``True`` to allow the use of the
+                                      Werkzeug web server in a production
+                                      setting. Default is ``False``. Set to
+                                      ``True`` at your own risk.
         :param kwargs: Additional web server options. The web server options
                        are specific to the server used in each of the supported
                        async modes. Note that options provided here will
@@ -593,6 +634,20 @@
                 from werkzeug._internal import _log
                 _log('warning', 'WebSocket transport not available. Install '
                                 'simple-websocket for improved performance.')
+            allow_unsafe_werkzeug = kwargs.pop('allow_unsafe_werkzeug',
+                                               False)
+            if not sys.stdin or not sys.stdin.isatty():  # pragma: no cover
+                if not allow_unsafe_werkzeug:
+                    raise RuntimeError('The Werkzeug web server is not '
+                                       'designed to run in production. Pass '
+                                       'allow_unsafe_werkzeug=True to the '
+                                       'run() method to disable this error.')
+                else:
+                    from werkzeug._internal import _log
+                    _log('warning', ('Werkzeug appears to be used in a '
+                                     'production deployment. Consider '
+                                     'switching to a production web server '
+                                     'instead.'))
             app.run(host=host, port=port, threaded=True,
                     use_reloader=use_reloader, **reloader_options, **kwargs)
         elif self.server.eio.async_mode == 'eventlet':
@@ -690,9 +745,9 @@
         :param args: arguments to pass to the function.
         :param kwargs: keyword arguments to pass to the function.
 
-        This function returns an object compatible with the `Thread` class in
-        the Python standard library. The `start()` method on this object is
-        already called by this function.
+        This function returns an object that represents the background task,
+        on which the ``join()`` method can be invoked to wait for the task to
+        complete.
         """
         return self.server.start_background_task(target, *args, **kwargs)
 
@@ -744,6 +799,14 @@
                 if 'saved_session' not in environ:
                     environ['saved_session'] = _ManagedSession(flask.session)
                 session_obj = environ['saved_session']
+                if hasattr(flask, 'globals') and \
+                        hasattr(flask.globals, 'request_ctx'):
+                    # update session for Flask >= 2.2
+                    ctx = flask.globals.request_ctx._get_current_object()
+                else:  # pragma: no cover
+                    # update session for Flask < 2.2
+                    ctx = flask._request_ctx_stack.top
+                ctx.session = session_obj
             else:
                 # let Flask handle the user session
                 # for cookie based sessions, this effectively freezes the
@@ -751,7 +814,6 @@
                 # for server-side sessions, this allows HTTP and Socket.IO to
                 # share the session, with both having read/write access to it
                 session_obj = flask.session._get_current_object()
-            _request_ctx_stack.top.session = session_obj
             flask.request.sid = sid
             flask.request.namespace = namespace
             flask.request.event = {'message': message, 'args': args}
@@ -764,6 +826,8 @@
                         ret = handler()
                 else:
                     ret = handler(*args)
+            except ConnectionRefusedError:
+                raise  # let this error bubble up to python-socketio
             except:
                 err_handler = self.exception_handlers.get(
                     namespace, self.default_exception_handler)
@@ -802,9 +866,10 @@
                      acknowledgement.
     :param broadcast: ``True`` to send the message to all clients, or ``False``
                       to only reply to the sender of the originating event.
-    :param to: Send the message to all the users in the given room. If this
-               argument is not set and ``broadcast`` is ``False``, then the
-               message is sent only to the originating user.
+    :param to: Send the message to all the users in the given room, or to the
+               user with the given session ID. If this argument is not set and
+               ``broadcast`` is ``False``, then the message is sent only to the
+               originating user.
     :param include_self: ``True`` to include the sender when broadcasting or
                          addressing a room, or ``False`` to send to everyone
                          but the sender.
@@ -827,7 +892,7 @@
         namespace = flask.request.namespace
     callback = kwargs.get('callback')
     broadcast = kwargs.get('broadcast')
-    to = kwargs.pop('to', kwargs.pop('room', None))
+    to = kwargs.pop('to', None) or kwargs.pop('room', None)
     if to is None and not broadcast:
         to = flask.request.sid
     include_self = kwargs.get('include_self', True)
@@ -840,6 +905,52 @@
                          callback=callback, ignore_queue=ignore_queue)
 
 
+def call(event, *args, **kwargs):  # pragma: no cover
+    """Emit a SocketIO event and wait for the response.
+
+    This function issues an emit with a callback and waits for the callback to
+    be invoked by the client before returning. If the callback isn’t invoked
+    before the timeout, then a TimeoutError exception is raised. If the
+    Socket.IO connection drops during the wait, this method still waits until
+    the specified timeout. Example::
+
+        def get_status(client, data):
+            status = call('status', {'data': data}, to=client)
+
+    :param event: The name of the user event to emit.
+    :param args: A dictionary with the JSON data to send as payload.
+    :param namespace: The namespace under which the message is to be sent.
+                      Defaults to the namespace used by the originating event.
+                      A ``'/'`` can be used to explicitly specify the global
+                      namespace.
+    :param to: The session ID of the recipient client. If this argument is not
+               given, the event is sent to the originating client.
+    :param timeout: The waiting timeout. If the timeout is reached before the
+                    client acknowledges the event, then a ``TimeoutError``
+                    exception is raised. The default is 60 seconds.
+    :param ignore_queue: Only used when a message queue is configured. If
+                         set to ``True``, the event is emitted to the
+                         client directly, without going through the queue.
+                         This is more efficient, but only works when a
+                         single server process is used, or when there is a
+                         single addressee. It is recommended to always leave
+                         this parameter with its default value of ``False``.
+    """
+    if 'namespace' in kwargs:
+        namespace = kwargs['namespace']
+    else:
+        namespace = flask.request.namespace
+    to = kwargs.pop('to', None) or kwargs.pop('room', None)
+    if to is None:
+        to = flask.request.sid
+    timeout = kwargs.get('timeout', 60)
+    ignore_queue = kwargs.get('ignore_queue', False)
+
+    socketio = flask.current_app.extensions['socketio']
+    return socketio.call(event, *args, namespace=namespace, to=to,
+                         ignore_queue=ignore_queue, timeout=timeout)
+
+
 def send(message, **kwargs):
     """Send a SocketIO message.
 
@@ -859,9 +970,10 @@
     :param broadcast: ``True`` to send the message to all connected clients, or
                       ``False`` to only reply to the sender of the originating
                       event.
-    :param to: Send the message to all the users in the given room. If this
-               argument is not set and ``broadcast`` is ``False``, then the
-               message is sent only to the originating user.
+    :param to: Send the message to all the users in the given room, or to the
+               user with the given session ID. If this argument is not set and
+               ``broadcast`` is ``False``, then the message is sent only to the
+               originating user.
     :param include_self: ``True`` to include the sender when broadcasting or
                          addressing a room, or ``False`` to send to everyone
                          but the sender.
@@ -885,7 +997,7 @@
         namespace = flask.request.namespace
     callback = kwargs.get('callback')
     broadcast = kwargs.get('broadcast')
-    to = kwargs.pop('to', kwargs.pop('room', None))
+    to = kwargs.pop('to', None) or kwargs.pop('room', None)
     if to is None and not broadcast:
         to = flask.request.sid
     include_self = kwargs.get('include_self', True)
@@ -910,7 +1022,7 @@
             username = session['username']
             room = data['room']
             join_room(room)
-            send(username + ' has entered the room.', room=room)
+            send(username + ' has entered the room.', to=room)
 
     :param room: The name of the room to join.
     :param sid: The session id of the client. If not provided, the client is
@@ -935,7 +1047,7 @@
             username = session['username']
             room = data['room']
             leave_room(room)
-            send(username + ' has left the room.', room=room)
+            send(username + ' has left the room.', to=room)
 
     :param room: The name of the room to leave.
     :param sid: The session id of the client. If not provided, the client is
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/Flask-SocketIO-5.1.1/src/flask_socketio/test_client.py 
new/Flask-SocketIO-5.3.4/src/flask_socketio/test_client.py
--- old/Flask-SocketIO-5.1.1/src/flask_socketio/test_client.py  2021-06-13 
17:46:50.000000000 +0200
+++ new/Flask-SocketIO-5.3.4/src/flask_socketio/test_client.py  2023-05-03 
12:28:48.000000000 +0200
@@ -24,8 +24,7 @@
                               cookies set in HTTP routes accessible from
                               Socket.IO events.
     """
-    queue = {}
-    acks = {}
+    clients = {}
 
     def __init__(self, app, socketio, namespace=None, query_string=None,
                  headers=None, auth=None, flask_test_client=None):
@@ -38,35 +37,37 @@
                 pkt = packet.Packet(encoded_packet=epkt[0])
                 for att in epkt[1:]:
                     pkt.add_attachment(att)
+            client = self.clients.get(eio_sid)
+            if not client:
+                return
             if pkt.packet_type == packet.EVENT or \
                     pkt.packet_type == packet.BINARY_EVENT:
-                if eio_sid not in self.queue:
-                    self.queue[eio_sid] = []
                 if pkt.data[0] == 'message' or pkt.data[0] == 'json':
-                    self.queue[eio_sid].append({
+                    client.queue.append({
                         'name': pkt.data[0],
                         'args': pkt.data[1],
                         'namespace': pkt.namespace or '/'})
                 else:
-                    self.queue[eio_sid].append({
+                    client.queue.append({
                         'name': pkt.data[0],
                         'args': pkt.data[1:],
                         'namespace': pkt.namespace or '/'})
             elif pkt.packet_type == packet.ACK or \
                     pkt.packet_type == packet.BINARY_ACK:
-                self.acks[eio_sid] = {'args': pkt.data,
-                                      'namespace': pkt.namespace or '/'}
+                client.acks = {'args': pkt.data,
+                               'namespace': pkt.namespace or '/'}
             elif pkt.packet_type in [packet.DISCONNECT, packet.CONNECT_ERROR]:
-                self.connected[pkt.namespace or '/'] = False
+                client.connected[pkt.namespace or '/'] = False
 
         self.app = app
         self.flask_test_client = flask_test_client
         self.eio_sid = uuid.uuid4().hex
-        self.acks[self.eio_sid] = None
-        self.queue[self.eio_sid] = []
+        self.clients[self.eio_sid] = self
         self.callback_counter = 0
         self.socketio = socketio
         self.connected = {}
+        self.queue = []
+        self.acks = None
         socketio.server._send_packet = _mock_send_packet
         socketio.server.environ[self.eio_sid] = {}
         socketio.server.async_handlers = False      # easier to test when
@@ -113,12 +114,15 @@
         environ['flask.app'] = self.app
         if self.flask_test_client:
             # inject cookies from Flask
-            self.flask_test_client.cookie_jar.inject_wsgi(environ)
+            if hasattr(self.flask_test_client, '_add_cookies_to_wsgi'):
+                # flask >= 2.3
+                self.flask_test_client._add_cookies_to_wsgi(environ)
+            else:  # pragma: no cover
+                # flask < 2.3
+                self.flask_test_client.cookie_jar.inject_wsgi(environ)
         self.socketio.server._handle_eio_connect(self.eio_sid, environ)
         pkt = packet.Packet(packet.CONNECT, auth, namespace=namespace)
-        with self.app.app_context():
-            self.socketio.server._handle_eio_message(self.eio_sid,
-                                                     pkt.encode())
+        self.socketio.server._handle_eio_message(self.eio_sid, pkt.encode())
         sid = self.socketio.server.manager.sid_from_eio_sid(self.eio_sid,
                                                             namespace)
         if sid:
@@ -133,9 +137,7 @@
         if not self.is_connected(namespace):
             raise RuntimeError('not connected')
         pkt = packet.Packet(packet.DISCONNECT, namespace=namespace)
-        with self.app.app_context():
-            self.socketio.server._handle_eio_message(self.eio_sid,
-                                                     pkt.encode())
+        self.socketio.server._handle_eio_message(self.eio_sid, pkt.encode())
         del self.connected[namespace or '/']
 
     def emit(self, event, *args, **kwargs):
@@ -163,17 +165,15 @@
             id = self.callback_counter
         pkt = packet.Packet(packet.EVENT, data=[event] + list(args),
                             namespace=namespace, id=id)
-        with self.app.app_context():
-            encoded_pkt = pkt.encode()
-            if isinstance(encoded_pkt, list):
-                for epkt in encoded_pkt:
-                    self.socketio.server._handle_eio_message(self.eio_sid,
-                                                             epkt)
-            else:
-                self.socketio.server._handle_eio_message(self.eio_sid,
-                                                         encoded_pkt)
-        ack = self.acks.pop(self.eio_sid, None)
-        if ack is not None:
+        encoded_pkt = pkt.encode()
+        if isinstance(encoded_pkt, list):
+            for epkt in encoded_pkt:
+                self.socketio.server._handle_eio_message(self.eio_sid, epkt)
+        else:
+            self.socketio.server._handle_eio_message(self.eio_sid, encoded_pkt)
+        if self.acks is not None:
+            ack = self.acks
+            self.acks = None
             return ack['args'][0] if len(ack['args']) == 1 \
                 else ack['args']
 
@@ -213,8 +213,6 @@
         if not self.is_connected(namespace):
             raise RuntimeError('not connected')
         namespace = namespace or '/'
-        r = [pkt for pkt in self.queue[self.eio_sid]
-             if pkt['namespace'] == namespace]
-        self.queue[self.eio_sid] = [
-            pkt for pkt in self.queue[self.eio_sid] if pkt not in r]
+        r = [pkt for pkt in self.queue if pkt['namespace'] == namespace]
+        self.queue = [pkt for pkt in self.queue if pkt not in r]
         return r

++++++ test_socketio.py ++++++
--- /var/tmp/diff_new_pack.p8vss1/_old  2023-06-22 23:26:32.021986196 +0200
+++ /var/tmp/diff_new_pack.p8vss1/_new  2023-06-22 23:26:32.021986196 +0200
@@ -3,7 +3,7 @@
 
 from flask import Flask, session, request, json as flask_json
 from flask_socketio import SocketIO, send, emit, join_room, leave_room, \
-    Namespace, disconnect
+    Namespace, disconnect, ConnectionRefusedError
 
 app = Flask(__name__)
 app.config['SECRET_KEY'] = 'secret'
@@ -16,11 +16,12 @@
     if auth != {'foo': 'bar'}:  # pragma: no cover
         return False
     if request.args.get('fail'):
-        return False
+        raise ConnectionRefusedError('failed!')
     send('connected')
     send(json.dumps(request.args.to_dict(flat=False)))
     send(json.dumps({h: request.headers[h] for h in request.headers.keys()
                      if h not in ['Host', 'Content-Type', 'Content-Length']}))
+    emit('dummy', to='nobody')
 
 
 @socketio.on('disconnect')
@@ -47,7 +48,12 @@
 def message(message):
     send(message)
     if message == 'test session':
-        session['a'] = 'b'
+        if not socketio.manage_session and 'a' in session:
+            raise RuntimeError('session is being stored')
+        if 'a' not in session:
+            session['a'] = 'b'
+        else:
+            session['a'] = 'c'
     if message not in "test noackargs":
         return message
 
@@ -345,6 +351,25 @@
         client.disconnect('/test')
         self.assertEqual(disconnected, '/test')
 
+    def test_message_queue_options(self):
+        app = Flask(__name__)
+        socketio = SocketIO(app, message_queue='redis://')
+        self.assertFalse(socketio.server_options['client_manager'].write_only)
+
+        app = Flask(__name__)
+        socketio = SocketIO(app)
+        socketio.init_app(app, message_queue='redis://')
+        self.assertFalse(socketio.server_options['client_manager'].write_only)
+
+        app = Flask(__name__)
+        socketio = SocketIO(message_queue='redis://')
+        self.assertTrue(socketio.server_options['client_manager'].write_only)
+
+        app = Flask(__name__)
+        socketio = SocketIO()
+        socketio.init_app(None, message_queue='redis://')
+        self.assertTrue(socketio.server_options['client_manager'].write_only)
+
     def test_send(self):
         client = socketio.test_client(app, auth={'foo': 'bar'})
         client.get_received()
@@ -454,7 +479,7 @@
         self.assertEqual(received[0]['args'][0]['a'], 'b')
         self.assertEqual(len(client3.get_received()), 0)
 
-    def test_session(self):
+    def test_managed_session(self):
         flask_client = app.test_client()
         flask_client.get('/session')
         client = socketio.test_client(app, flask_test_client=flask_client,
@@ -468,6 +493,21 @@
         self.assertEqual(
             socketio.server.environ[client.eio_sid]['saved_session'],
             {'a': 'b', 'foo': 'bar'})
+        client.send('test session')
+        self.assertEqual(
+            socketio.server.environ[client.eio_sid]['saved_session'],
+            {'a': 'c', 'foo': 'bar'})
+
+    def test_unmanaged_session(self):
+        socketio.manage_session = False
+        flask_client = app.test_client()
+        flask_client.get('/session')
+        client = socketio.test_client(app, flask_test_client=flask_client,
+                                      auth={'foo': 'bar'})
+        client.get_received()
+        client.send('test session')
+        client.send('test session')
+        socketio.manage_session = True
 
     def test_room(self):
         client1 = socketio.test_client(app, auth={'foo': 'bar'})
@@ -647,11 +687,18 @@
 
     def test_server_disconnected(self):
         client = socketio.test_client(app, namespace='/ns')
+        client2 = socketio.test_client(app, namespace='/ns')
         client.get_received('/ns')
+        client2.get_received('/ns')
         client.emit('exit', {}, namespace='/ns')
         self.assertFalse(client.is_connected('/ns'))
+        self.assertTrue(client2.is_connected('/ns'))
         with self.assertRaises(RuntimeError):
             client.emit('hello', {}, namespace='/ns')
+        client2.emit('exit', {}, namespace='/ns')
+        self.assertFalse(client2.is_connected('/ns'))
+        with self.assertRaises(RuntimeError):
+            client2.emit('hello', {}, namespace='/ns')
 
     def test_emit_class_based(self):
         client = socketio.test_client(app, namespace='/ns')

Reply via email to