Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package python-python-socketio for 
openSUSE:Factory checked in at 2022-01-24 23:10:12
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-python-socketio (Old)
 and      /work/SRC/openSUSE:Factory/.python-python-socketio.new.1938 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-python-socketio"

Mon Jan 24 23:10:12 2022 rev:5 rq:948409 version:5.5.1

Changes:
--------
--- 
/work/SRC/openSUSE:Factory/python-python-socketio/python-python-socketio.changes
    2021-10-26 20:14:22.950031635 +0200
+++ 
/work/SRC/openSUSE:Factory/.python-python-socketio.new.1938/python-python-socketio.changes
  2022-01-24 23:10:49.614416413 +0100
@@ -1,0 +2,19 @@
+Sun Jan 23 08:34:21 UTC 2022 - Axel Braun <axel.br...@gmx.de>
+
+- version 5.5.1
+  * Support multiple Kafka servers (thanks sparkingdark!)
+  * Include example code in flake8 pass 
+  * Option to disable the SIGINT handler in the client #792 
+  * Do not invoke reserved events on a catch-all handler #814 
+  * Use correct binary packet types in the msgpack packet encoder #811 
+  * Add missing call() method to namespace classes #800 
+  * Add missing to argument to namespace emit() and send() methods #810 
+  * Configure Redis pubsub to skip subscription messages 
+  * Migrate async Redis client manager to aioredis 2 #771 (thanks Sam Mosleh!)
+  * Update Python supported versions in docs 
+  * Document how to get the connection state in the client #799 
+  * Improved documentation of start_background_task() function 
+  * Improved documentation of call() method #813 
+  * Fixed intermittent test failures #572 
+
+-------------------------------------------------------------------
@@ -5,2 +24,2 @@
-  * Catch-all event handlers (commit)
-  * Implement disconnect method for external processes #684 (commit) 
+  * Catch-all event handlers 
+  * Implement disconnect method for external processes #684 

Old:
----
  python-socketio-5.4.1.tar.gz

New:
----
  python-socketio-5.5.1.tar.gz

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

Other differences:
------------------
++++++ python-python-socketio.spec ++++++
--- /var/tmp/diff_new_pack.s3Snih/_old  2022-01-24 23:10:50.090413160 +0100
+++ /var/tmp/diff_new_pack.s3Snih/_new  2022-01-24 23:10:50.094413133 +0100
@@ -1,7 +1,7 @@
 #
 # spec file for package python-python-socketio
 #
-# Copyright (c) 2021 SUSE LLC
+# Copyright (c) 2022 SUSE LLC
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -19,7 +19,7 @@
 %{?!python_module:%define python_module() python3-%{**}}
 %define skip_python2 1
 Name:           python-python-socketio
-Version:        5.4.1
+Version:        5.5.1
 Release:        0
 Summary:        SocketIO server
 License:        MIT

++++++ python-socketio-5.4.1.tar.gz -> python-socketio-5.5.1.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python-socketio-5.4.1/CHANGES.md 
new/python-socketio-5.5.1/CHANGES.md
--- old/python-socketio-5.4.1/CHANGES.md        2021-10-14 21:19:50.000000000 
+0200
+++ new/python-socketio-5.5.1/CHANGES.md        2022-01-11 13:17:25.000000000 
+0100
@@ -1,5 +1,25 @@
 # python-socketio change log
 
+**Release 5.5.1** - 2022-01-11
+
+- Support multiple Kafka servers 
([commit](https://github.com/miguelgrinberg/python-socketio/commit/4ee3649514b98c50cc0bf70d3f269389da52772d))
 (thanks **sparkingdark**!)
+- Include example code in flake8 pass 
([commit](https://github.com/miguelgrinberg/python-socketio/commit/273a4b0439c84560d403662d8eba4122c28ba0d8))
+
+**Release 5.5.0** - 2021-11-14
+
+- Option to disable the SIGINT handler in the client 
[#792](https://github.com/miguelgrinberg/python-socketio/issues/792) 
([commit](https://github.com/miguelgrinberg/python-socketio/commit/ea84b9b1c714b02eaf1081f4e37fd130a3159d8c))
+- Do not invoke reserved events on a catch-all handler 
[#814](https://github.com/miguelgrinberg/python-socketio/issues/814) 
([commit](https://github.com/miguelgrinberg/python-socketio/commit/34f34e53d650dde605f5f4a98d7a70936524a1b8))
+- Use correct binary packet types in the msgpack packet encoder 
[#811](https://github.com/miguelgrinberg/python-socketio/issues/811) 
([commit](https://github.com/miguelgrinberg/python-socketio/commit/60735dd4c2fc87ed863d7dbf7de361500d963dd3))
+- Add missing `call()` method to namespace classes 
[#800](https://github.com/miguelgrinberg/python-socketio/issues/800) 
([commit](https://github.com/miguelgrinberg/python-socketio/commit/32db48d12ceb44d7a02fd9f05047b47c7ed3f4a5))
+- Add missing `to` argument to namespace `emit()` and `send()` methods 
[#810](https://github.com/miguelgrinberg/python-socketio/issues/810) 
([commit](https://github.com/miguelgrinberg/python-socketio/commit/ed08a01e65635160923f3d6d5755df74d53274e1))
+- Configure Redis pubsub to skip subscription messages 
([commit](https://github.com/miguelgrinberg/python-socketio/commit/e8fff07b367929794e5e30cecbf252b72d307c16))
+- Migrate async Redis client manager to aioredis 2 
[#771](https://github.com/miguelgrinberg/python-socketio/issues/771) 
([commit](https://github.com/miguelgrinberg/python-socketio/commit/f245191d86722244a2d3d0529d9f5ff15dfd817a))
 (thanks **Sam Mosleh**!)
+- Update Python supported versions in docs 
([commit](https://github.com/miguelgrinberg/python-socketio/commit/a54152f2466bad4869d9cfdad6be3a5547e0b6bc))
+- Document how to get the connection state in the client 
[#799](https://github.com/miguelgrinberg/python-socketio/issues/799) 
([commit](https://github.com/miguelgrinberg/python-socketio/commit/47c5f45c765ae207f58ba2675f91eaf8c79f8500))
+- Improved documentation of `start_background_task()` function 
([commit](https://github.com/miguelgrinberg/python-socketio/commit/4f5bf1e9898154aa1a9896a7016ba22bfb73cdf2))
+- Improved documentation of `call()` method 
[#813](https://github.com/miguelgrinberg/python-socketio/issues/813) 
([commit](https://github.com/miguelgrinberg/python-socketio/commit/8c2a6ac86972bf94acafe687d2e86bdf65119960))
+- Fixed intermittent test failures 
[#572](https://github.com/miguelgrinberg/python-socketio/issues/572) 
([commit](https://github.com/miguelgrinberg/python-socketio/commit/db0565ada6c8891be3230bcc415e5465bd409c09))
+
 **Release 5.4.1** - 2021-10-14
 
 - Catch-all event handlers 
([commit](https://github.com/miguelgrinberg/python-socketio/commit/28569d48ad74d5414a0d2a8f69d7540dbdddf066))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python-socketio-5.4.1/docs/api.rst 
new/python-socketio-5.5.1/docs/api.rst
--- old/python-socketio-5.4.1/docs/api.rst      2021-10-14 21:19:50.000000000 
+0200
+++ new/python-socketio-5.5.1/docs/api.rst      2022-01-11 13:17:25.000000000 
+0100
@@ -35,7 +35,7 @@
 ``ConnectionRefusedError`` class
 --------------------------------
 
-.. autoclass:: ConnectionRefusedError
+.. autoclass:: socketio.exceptions.ConnectionRefusedError
    :members:
 
 ``WSGIApp`` class
@@ -128,7 +128,7 @@
    :members:
 
 ``AsyncAioPikaManager`` class
----------------------------
+-----------------------------
 
 .. autoclass:: AsyncAioPikaManager
    :members:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python-socketio-5.4.1/docs/client.rst 
new/python-socketio-5.5.1/docs/client.rst
--- old/python-socketio-5.4.1/docs/client.rst   2021-10-14 21:19:50.000000000 
+0200
+++ new/python-socketio-5.5.1/docs/client.rst   2022-01-11 13:17:25.000000000 
+0100
@@ -65,6 +65,9 @@
     async def message(data):
         print('I received a message!')
 
+If the server includes arguments with an event, those are passed to the
+handler function as arguments.
+
 Catch-All Event Handlers
 ------------------------
 
@@ -72,13 +75,13 @@
 event handler. You can define a catch-all handler using ``'*'`` as event name::
 
    @sio.on('*')
-   def catch_all(event, sid, data):
+   def catch_all(event, data):
        pass
 
 Asyncio clients can also use a coroutine::
 
    @sio.on('*')
-   async def catch_all(event, sid, data):
+   async def catch_all(event, data):
       pass
 
 A catch-all event handler receives the event name as a first argument. The
@@ -115,8 +118,8 @@
 handler. As soon as the connection is re-established the connect handler will
 be invoked once again.
 
-If the server includes arguments with an event, those are passed to the
-handler function as arguments.
+The ``connect``, ``connect_error`` and ``disconnect`` events have to be
+defined explicitly and are not invoked on a catch-all event handler.
 
 Connecting to a Server
 ----------------------
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python-socketio-5.4.1/docs/intro.rst 
new/python-socketio-5.5.1/docs/intro.rst
--- old/python-socketio-5.4.1/docs/intro.rst    2021-10-14 21:19:50.000000000 
+0200
+++ new/python-socketio-5.5.1/docs/intro.rst    2022-01-11 13:17:25.000000000 
+0100
@@ -103,7 +103,7 @@
 - Can connect to other Socket.IO servers that are compatible with the
   JavaScript Socket.IO 1.x and 2.x releases. Work to support release 3.x is in
   progress.
-- Compatible with Python 3.5+.
+- Compatible with Python 3.6+.
 - Two versions of the client, one for standard Python and another for
   asyncio.
 - Uses an event-based architecture implemented with decorators that
@@ -183,7 +183,7 @@
 - Can connect to servers running other Socket.IO clients that are compatible
   with the JavaScript client versions 1.x and 2.x. Work to support the 3.x
   release is in progress.
-- Compatible with Python 3.5+.
+- Compatible with Python 3.6+.
 - Two versions of the server, one for standard Python and another for
   asyncio.
 - Supports large number of clients even on modest hardware due to being
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python-socketio-5.4.1/docs/server.rst 
new/python-socketio-5.5.1/docs/server.rst
--- old/python-socketio-5.4.1/docs/server.rst   2021-10-14 21:19:50.000000000 
+0200
+++ new/python-socketio-5.5.1/docs/server.rst   2022-01-11 13:17:25.000000000 
+0100
@@ -197,6 +197,9 @@
 A catch-all event handler receives the event name as a first argument. The
 remaining arguments are the same as for a regular event handler.
 
+The ``connect`` and ``disconnect`` events have to be defined explicitly and are
+not invoked on a catch-all event handler.
+
 Connect and Disconnect Event Handlers
 -------------------------------------
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python-socketio-5.4.1/examples/server/aiohttp/app.py 
new/python-socketio-5.5.1/examples/server/aiohttp/app.py
--- old/python-socketio-5.4.1/examples/server/aiohttp/app.py    2021-10-14 
21:19:50.000000000 +0200
+++ new/python-socketio-5.5.1/examples/server/aiohttp/app.py    2022-01-11 
13:17:25.000000000 +0100
@@ -1,5 +1,3 @@
-import asyncio
-
 from aiohttp import web
 
 import socketio
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python-socketio-5.4.1/examples/server/asgi/app.py 
new/python-socketio-5.5.1/examples/server/asgi/app.py
--- old/python-socketio-5.4.1/examples/server/asgi/app.py       2021-10-14 
21:19:50.000000000 +0200
+++ new/python-socketio-5.5.1/examples/server/asgi/app.py       2022-01-11 
13:17:25.000000000 +0100
@@ -1,6 +1,4 @@
 #!/usr/bin/env python
-import asyncio
-
 import uvicorn
 
 import socketio
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python-socketio-5.4.1/examples/server/sanic/app.py 
new/python-socketio-5.5.1/examples/server/sanic/app.py
--- old/python-socketio-5.4.1/examples/server/sanic/app.py      2021-10-14 
21:19:50.000000000 +0200
+++ new/python-socketio-5.5.1/examples/server/sanic/app.py      2022-01-11 
13:17:25.000000000 +0100
@@ -1,5 +1,3 @@
-import asyncio
-
 from sanic import Sanic
 from sanic.response import html
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python-socketio-5.4.1/examples/server/tornado/app.py 
new/python-socketio-5.5.1/examples/server/tornado/app.py
--- old/python-socketio-5.4.1/examples/server/tornado/app.py    2021-10-14 
21:19:50.000000000 +0200
+++ new/python-socketio-5.5.1/examples/server/tornado/app.py    2022-01-11 
13:17:25.000000000 +0100
@@ -42,6 +42,7 @@
     await sio.emit('my_response', {'data': 'Entered room: ' + message['room']},
                    room=sid)
 
+
 @sio.event
 async def leave(sid, message):
     sio.leave_room(sid, message['room'])
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python-socketio-5.4.1/examples/server/wsgi/app.py 
new/python-socketio-5.5.1/examples/server/wsgi/app.py
--- old/python-socketio-5.4.1/examples/server/wsgi/app.py       2021-10-14 
21:19:50.000000000 +0200
+++ new/python-socketio-5.5.1/examples/server/wsgi/app.py       2022-01-11 
13:17:25.000000000 +0100
@@ -3,7 +3,6 @@
 # installed
 async_mode = None
 
-import time
 from flask import Flask, render_template
 import socketio
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/python-socketio-5.4.1/examples/server/wsgi/django_example/django_example/settings.py
 
new/python-socketio-5.5.1/examples/server/wsgi/django_example/django_example/settings.py
--- 
old/python-socketio-5.4.1/examples/server/wsgi/django_example/django_example/settings.py
    2021-10-14 21:19:50.000000000 +0200
+++ 
new/python-socketio-5.5.1/examples/server/wsgi/django_example/django_example/settings.py
    2022-01-11 13:17:25.000000000 +0100
@@ -1,3 +1,4 @@
+# flake8: noqa
 """
 Django settings for django_example project.
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/python-socketio-5.4.1/examples/server/wsgi/django_example/manage.py 
new/python-socketio-5.5.1/examples/server/wsgi/django_example/manage.py
--- old/python-socketio-5.4.1/examples/server/wsgi/django_example/manage.py     
2021-10-14 21:19:50.000000000 +0200
+++ new/python-socketio-5.5.1/examples/server/wsgi/django_example/manage.py     
2022-01-11 13:17:25.000000000 +0100
@@ -1,4 +1,5 @@
 #!/usr/bin/env python
+# flake8: noqa
 import os
 import sys
 
@@ -11,7 +12,7 @@
         # issue is really that Django is missing to avoid masking other
         # exceptions on Python 2.
         try:
-            import django
+            import django  # pragma: F401
         except ImportError:
             raise ImportError(
                 "Couldn't import Django. Are you sure it's installed and "
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/python-socketio-5.4.1/examples/server/wsgi/django_example/socketio_app/admin.py
 
new/python-socketio-5.5.1/examples/server/wsgi/django_example/socketio_app/admin.py
--- 
old/python-socketio-5.4.1/examples/server/wsgi/django_example/socketio_app/admin.py
 2021-10-14 21:19:50.000000000 +0200
+++ 
new/python-socketio-5.5.1/examples/server/wsgi/django_example/socketio_app/admin.py
 2022-01-11 13:17:25.000000000 +0100
@@ -1,3 +1,4 @@
+# flake8: noqa
 from django.contrib import admin
 
 # Register your models here.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/python-socketio-5.4.1/examples/server/wsgi/django_example/socketio_app/models.py
 
new/python-socketio-5.5.1/examples/server/wsgi/django_example/socketio_app/models.py
--- 
old/python-socketio-5.4.1/examples/server/wsgi/django_example/socketio_app/models.py
        2021-10-14 21:19:50.000000000 +0200
+++ 
new/python-socketio-5.5.1/examples/server/wsgi/django_example/socketio_app/models.py
        2022-01-11 13:17:25.000000000 +0100
@@ -1,3 +1,4 @@
+# flake8: noqa
 from django.db import models
 
 # Create your models here.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/python-socketio-5.4.1/examples/server/wsgi/django_example/socketio_app/tests.py
 
new/python-socketio-5.5.1/examples/server/wsgi/django_example/socketio_app/tests.py
--- 
old/python-socketio-5.4.1/examples/server/wsgi/django_example/socketio_app/tests.py
 2021-10-14 21:19:50.000000000 +0200
+++ 
new/python-socketio-5.5.1/examples/server/wsgi/django_example/socketio_app/tests.py
 2022-01-11 13:17:25.000000000 +0100
@@ -1,3 +1,4 @@
+# flake8: noqa
 from django.test import TestCase
 
 # Create your tests here.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/python-socketio-5.4.1/examples/server/wsgi/django_example/socketio_app/views.py
 
new/python-socketio-5.5.1/examples/server/wsgi/django_example/socketio_app/views.py
--- 
old/python-socketio-5.4.1/examples/server/wsgi/django_example/socketio_app/views.py
 2021-10-14 21:19:50.000000000 +0200
+++ 
new/python-socketio-5.5.1/examples/server/wsgi/django_example/socketio_app/views.py
 2022-01-11 13:17:25.000000000 +0100
@@ -80,4 +80,3 @@
 @sio.event
 def disconnect(sid):
     print('Client disconnected')
-
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python-socketio-5.4.1/setup.cfg 
new/python-socketio-5.5.1/setup.cfg
--- old/python-socketio-5.4.1/setup.cfg 2021-10-14 21:19:50.000000000 +0200
+++ new/python-socketio-5.5.1/setup.cfg 2022-01-11 13:17:25.000000000 +0100
@@ -1,6 +1,6 @@
 [metadata]
 name = python-socketio
-version = 5.4.1
+version = 5.5.1
 author = Miguel Grinberg
 author_email = miguel.grinb...@gmail.com
 description = Socket.IO server and client for Python
@@ -25,7 +25,7 @@
 python_requires = >=3.6
 install_requires =
     bidict >= 0.21.0
-    python-engineio >= 4.1.0
+    python-engineio >= 4.3.0
 
 [options.packages.find]
 where = src
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/python-socketio-5.4.1/src/socketio/asyncio_aiopika_manager.py 
new/python-socketio-5.5.1/src/socketio/asyncio_aiopika_manager.py
--- old/python-socketio-5.4.1/src/socketio/asyncio_aiopika_manager.py   
2021-10-14 21:19:50.000000000 +0200
+++ new/python-socketio-5.5.1/src/socketio/asyncio_aiopika_manager.py   
2022-01-11 13:17:25.000000000 +0100
@@ -94,7 +94,7 @@
                 async with self.listener_queue.iterator() as queue_iter:
                     async for message in queue_iter:
                         with message.process():
-                            return pickle.loads(message.body)
+                            yield pickle.loads(message.body)
             except Exception:
                 self._get_logger().error('Cannot receive from rabbitmq... '
                                          'retrying in '
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python-socketio-5.4.1/src/socketio/asyncio_client.py 
new/python-socketio-5.5.1/src/socketio/asyncio_client.py
--- old/python-socketio-5.4.1/src/socketio/asyncio_client.py    2021-10-14 
21:19:50.000000000 +0200
+++ new/python-socketio-5.5.1/src/socketio/asyncio_client.py    2022-01-11 
13:17:25.000000000 +0100
@@ -40,6 +40,11 @@
                  packets. Custom json modules must have ``dumps`` and ``loads``
                  functions that are compatible with the standard library
                  versions.
+    :param handle_sigint: Set to ``True`` to automatically handle disconnection
+                          when the process is interrupted, or to ``False`` to
+                          leave interrupt handling to the calling application.
+                          Interrupt handling can only be enabled when the
+                          client instance is created in the main thread.
 
     The Engine.IO configuration supports the following settings:
 
@@ -249,6 +254,12 @@
     async def call(self, event, data=None, namespace=None, timeout=60):
         """Emit a custom event to a client and wait for the response.
 
+        This method issues an emit with a callback and waits for the callback
+        to be invoked 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.
+
         :param event: The event name. It can be any string. The event names
                       ``'connect'``, ``'message'`` and ``'disconnect'`` are
                       reserved and should not be used.
@@ -311,9 +322,7 @@
         :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.
+        The return value is a ``asyncio.Task`` object.
         """
         return self.eio.start_background_task(target, *args, **kwargs)
 
@@ -422,7 +431,8 @@
             handler = None
             if event in self.handlers[namespace]:
                 handler = self.handlers[namespace][event]
-            elif '*' in self.handlers[namespace]:
+            elif event not in self.reserved_events and \
+                    '*' in self.handlers[namespace]:
                 handler = self.handlers[namespace]['*']
                 args = (event, *args)
             if handler:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/python-socketio-5.4.1/src/socketio/asyncio_namespace.py 
new/python-socketio-5.5.1/src/socketio/asyncio_namespace.py
--- old/python-socketio-5.4.1/src/socketio/asyncio_namespace.py 2021-10-14 
21:19:50.000000000 +0200
+++ new/python-socketio-5.5.1/src/socketio/asyncio_namespace.py 2022-01-11 
13:17:25.000000000 +0100
@@ -41,7 +41,7 @@
                 ret = handler(*args)
             return ret
 
-    async def emit(self, event, data=None, room=None, skip_sid=None,
+    async def emit(self, event, data=None, to=None, room=None, skip_sid=None,
                    namespace=None, callback=None):
         """Emit a custom event to one or more connected clients.
 
@@ -51,13 +51,13 @@
 
         Note: this method is a coroutine.
         """
-        return await self.server.emit(event, data=data, room=room,
+        return await self.server.emit(event, data=data, to=to, room=room,
                                       skip_sid=skip_sid,
                                       namespace=namespace or self.namespace,
                                       callback=callback)
 
-    async def send(self, data, room=None, skip_sid=None, namespace=None,
-                   callback=None):
+    async def send(self, data, to=None, room=None, skip_sid=None,
+                   namespace=None, callback=None):
         """Send a message to one or more connected clients.
 
         The only difference with the :func:`socketio.Server.send` method is
@@ -66,10 +66,23 @@
 
         Note: this method is a coroutine.
         """
-        return await self.server.send(data, room=room, skip_sid=skip_sid,
+        return await self.server.send(data, to=to, room=room,
+                                      skip_sid=skip_sid,
                                       namespace=namespace or self.namespace,
                                       callback=callback)
 
+    async def call(self, event, data=None, to=None, sid=None, namespace=None,
+                   timeout=None):
+        """Emit a custom event to a client and wait for the response.
+
+        The only difference with the :func:`socketio.Server.call` method is
+        that when the ``namespace`` argument is not given the namespace
+        associated with the class is used.
+        """
+        return await self.server.call(event, data=data, to=to, sid=sid,
+                                      namespace=namespace or self.namespace,
+                                      timeout=timeout)
+
     async def close_room(self, room, namespace=None):
         """Close a room.
 
@@ -192,6 +205,17 @@
                                       namespace=namespace or self.namespace,
                                       callback=callback)
 
+    async def call(self, event, data=None, namespace=None, timeout=None):
+        """Emit a custom event to the server and wait for the response.
+
+        The only difference with the :func:`socketio.Client.call` method is
+        that when the ``namespace`` argument is not given the namespace
+        associated with the class is used.
+        """
+        return await self.client.call(event, data=data,
+                                      namespace=namespace or self.namespace,
+                                      timeout=timeout)
+
     async def disconnect(self):
         """Disconnect a client.
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/python-socketio-5.4.1/src/socketio/asyncio_pubsub_manager.py 
new/python-socketio-5.5.1/src/socketio/asyncio_pubsub_manager.py
--- old/python-socketio-5.4.1/src/socketio/asyncio_pubsub_manager.py    
2021-10-14 21:19:50.000000000 +0200
+++ new/python-socketio-5.5.1/src/socketio/asyncio_pubsub_manager.py    
2022-01-11 13:17:25.000000000 +0100
@@ -148,35 +148,34 @@
     async def _thread(self):
         while True:
             try:
-                message = await self._listen()
+                async for message in self._listen():  # pragma: no branch
+                    data = None
+                    if isinstance(message, dict):
+                        data = message
+                    else:
+                        if isinstance(message, bytes):  # pragma: no cover
+                            try:
+                                data = pickle.loads(message)
+                            except:
+                                pass
+                        if data is None:
+                            try:
+                                data = json.loads(message)
+                            except:
+                                pass
+                    if data and 'method' in data:
+                        self._get_logger().info('pubsub message: {}'.format(
+                            data['method']))
+                        if data['method'] == 'emit':
+                            await self._handle_emit(data)
+                        elif data['method'] == 'callback':
+                            await self._handle_callback(data)
+                        elif data['method'] == 'disconnect':
+                            await self._handle_disconnect(data)
+                        elif data['method'] == 'close_room':
+                            await self._handle_close_room(data)
             except asyncio.CancelledError:  # pragma: no cover
                 break
-            except:
+            except:  # pragma: no cover
                 import traceback
                 traceback.print_exc()
-                break
-            data = None
-            if isinstance(message, dict):
-                data = message
-            else:
-                if isinstance(message, bytes):  # pragma: no cover
-                    try:
-                        data = pickle.loads(message)
-                    except:
-                        pass
-                if data is None:
-                    try:
-                        data = json.loads(message)
-                    except:
-                        pass
-            if data and 'method' in data:
-                self._get_logger().info('pubsub message: {}'.format(
-                    data['method']))
-                if data['method'] == 'emit':
-                    await self._handle_emit(data)
-                elif data['method'] == 'callback':
-                    await self._handle_callback(data)
-                elif data['method'] == 'disconnect':
-                    await self._handle_disconnect(data)
-                elif data['method'] == 'close_room':
-                    await self._handle_close_room(data)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/python-socketio-5.4.1/src/socketio/asyncio_redis_manager.py 
new/python-socketio-5.5.1/src/socketio/asyncio_redis_manager.py
--- old/python-socketio-5.4.1/src/socketio/asyncio_redis_manager.py     
2021-10-14 21:19:50.000000000 +0200
+++ new/python-socketio-5.5.1/src/socketio/asyncio_redis_manager.py     
2022-01-11 13:17:25.000000000 +0100
@@ -1,6 +1,5 @@
 import asyncio
 import pickle
-from urllib.parse import urlparse
 
 try:
     import aioredis
@@ -10,34 +9,18 @@
 from .asyncio_pubsub_manager import AsyncPubSubManager
 
 
-def _parse_redis_url(url):
-    p = urlparse(url)
-    if p.scheme not in {'redis', 'rediss'}:
-        raise ValueError('Invalid redis url')
-    ssl = p.scheme == 'rediss'
-    host = p.hostname or 'localhost'
-    port = p.port or 6379
-    password = p.password
-    if p.path:
-        db = int(p.path[1:])
-    else:
-        db = 0
-    return host, port, password, db, ssl
-
-
 class AsyncRedisManager(AsyncPubSubManager):  # pragma: no cover
     """Redis based client manager for asyncio servers.
 
     This class implements a Redis backend for event sharing across multiple
-    processes. Only kept here as one more example of how to build a custom
-    backend, since the kombu backend is perfectly adequate to support a Redis
-    message queue.
+    processes.
 
-    To use a Redis backend, initialize the :class:`Server` instance as
+    To use a Redis backend, initialize the :class:`AsyncServer` instance as
     follows::
 
-        server = socketio.Server(client_manager=socketio.AsyncRedisManager(
-            'redis://hostname:port/0'))
+        url = 'redis://hostname:port/0'
+        server = socketio.AsyncServer(
+            client_manager=socketio.AsyncRedisManager(url))
 
     :param url: The connection URL for the Redis server. For a default Redis
                 store running on the same host, use ``redis://``.  To use an
@@ -47,62 +30,73 @@
     :param write_only: If set to ``True``, only initialize to emit events. The
                        default of ``False`` initializes the class for emitting
                        and receiving.
+    :param redis_options: additional keyword arguments to be passed to
+                          ``aioredis.from_url()``.
     """
     name = 'aioredis'
 
     def __init__(self, url='redis://localhost:6379/0', channel='socketio',
-                 write_only=False, logger=None):
+                 write_only=False, logger=None, redis_options=None):
         if aioredis is None:
             raise RuntimeError('Redis package is not installed '
                                '(Run "pip install aioredis" in your '
                                'virtualenv).')
-        (
-            self.host, self.port, self.password, self.db, self.ssl
-        ) = _parse_redis_url(url)
-        self.pub = None
-        self.sub = None
+        if not hasattr(aioredis.Redis, 'from_url'):
+            raise RuntimeError('Version 2 of aioredis package is required.')
+        self.redis_url = url
+        self.redis_options = redis_options or {}
+        self._redis_connect()
         super().__init__(channel=channel, write_only=write_only, logger=logger)
 
+    def _redis_connect(self):
+        self.redis = aioredis.Redis.from_url(self.redis_url,
+                                             **self.redis_options)
+        self.pubsub = self.redis.pubsub(ignore_subscribe_messages=True)
+
     async def _publish(self, data):
         retry = True
         while True:
             try:
-                if self.pub is None:
-                    self.pub = await aioredis.create_redis(
-                        (self.host, self.port), db=self.db,
-                        password=self.password, ssl=self.ssl
-                    )
-                return await self.pub.publish(self.channel,
-                                              pickle.dumps(data))
-            except (aioredis.RedisError, OSError):
+                if not retry:
+                    self._redis_connect()
+                return await self.redis.publish(
+                    self.channel, pickle.dumps(data))
+            except aioredis.exceptions.RedisError:
                 if retry:
                     self._get_logger().error('Cannot publish to redis... '
                                              'retrying')
-                    self.pub = None
                     retry = False
                 else:
                     self._get_logger().error('Cannot publish to redis... '
                                              'giving up')
                     break
 
-    async def _listen(self):
+    async def _redis_listen_with_retries(self):
         retry_sleep = 1
+        connect = False
         while True:
             try:
-                if self.sub is None:
-                    self.sub = await aioredis.create_redis(
-                        (self.host, self.port), db=self.db,
-                        password=self.password, ssl=self.ssl
-                    )
-                self.ch = (await self.sub.subscribe(self.channel))[0]
-                retry_sleep = 1
-                return await self.ch.get()
-            except (aioredis.RedisError, OSError):
+                if connect:
+                    self._redis_connect()
+                    await self.pubsub.subscribe(self.channel)
+                    retry_sleep = 1
+                async for message in self.pubsub.listen():
+                    yield message
+            except aioredis.exceptions.RedisError:
                 self._get_logger().error('Cannot receive from redis... '
                                          'retrying in '
                                          '{} secs'.format(retry_sleep))
-                self.sub = None
+                connect = True
                 await asyncio.sleep(retry_sleep)
                 retry_sleep *= 2
                 if retry_sleep > 60:
                     retry_sleep = 60
+
+    async def _listen(self):
+        channel = self.channel.encode('utf-8')
+        await self.pubsub.subscribe(self.channel)
+        async for message in self._redis_listen_with_retries():
+            if message['channel'] == channel and \
+                    message['type'] == 'message' and 'data' in message:
+                yield message['data']
+        await self.pubsub.unsubscribe(self.channel)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python-socketio-5.4.1/src/socketio/asyncio_server.py 
new/python-socketio-5.5.1/src/socketio/asyncio_server.py
--- old/python-socketio-5.4.1/src/socketio/asyncio_server.py    2021-10-14 
21:19:50.000000000 +0200
+++ new/python-socketio-5.5.1/src/socketio/asyncio_server.py    2022-01-11 
13:17:25.000000000 +0100
@@ -210,6 +210,12 @@
                    timeout=60, **kwargs):
         """Emit a custom event to a client and wait for the response.
 
+        This method issues an emit with a callback and waits for the callback
+        to be invoked 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.
+
         :param event: The event name. It can be any string. The event names
                       ``'connect'``, ``'message'`` and ``'disconnect'`` are
                       reserved and should not be used.
@@ -396,8 +402,6 @@
         :param kwargs: keyword arguments to pass to the function.
 
         The return value is a ``asyncio.Task`` object.
-
-        Note: this method is a coroutine.
         """
         return self.eio.start_background_task(target, *args, **kwargs)
 
@@ -528,7 +532,8 @@
             handler = None
             if event in self.handlers[namespace]:
                 handler = self.handlers[namespace][event]
-            elif '*' in self.handlers[namespace]:
+            elif event not in self.reserved_events and \
+                    '*' in self.handlers[namespace]:
                 handler = self.handlers[namespace]['*']
                 args = (event, *args)
             if handler:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python-socketio-5.4.1/src/socketio/client.py 
new/python-socketio-5.5.1/src/socketio/client.py
--- old/python-socketio-5.4.1/src/socketio/client.py    2021-10-14 
21:19:50.000000000 +0200
+++ new/python-socketio-5.5.1/src/socketio/client.py    2022-01-11 
13:17:25.000000000 +0100
@@ -68,6 +68,11 @@
                  packets. Custom json modules must have ``dumps`` and ``loads``
                  functions that are compatible with the standard library
                  versions.
+    :param handle_sigint: Set to ``True`` to automatically handle disconnection
+                          when the process is interrupted, or to ``False`` to
+                          leave interrupt handling to the calling application.
+                          Interrupt handling can only be enabled when the
+                          client instance is created in the main thread.
 
     The Engine.IO configuration supports the following settings:
 
@@ -87,12 +92,14 @@
                             fatal errors are logged even when
                             ``engineio_logger`` is ``False``.
     """
+    reserved_events = ['connect', 'connect_error', 'disconnect']
+
     def __init__(self, reconnection=True, reconnection_attempts=0,
                  reconnection_delay=1, reconnection_delay_max=5,
                  randomization_factor=0.5, logger=False, serializer='default',
-                 json=None, **kwargs):
+                 json=None, handle_sigint=True, **kwargs):
         global original_signal_handler
-        if original_signal_handler is None and \
+        if handle_sigint and original_signal_handler is None and \
                 threading.current_thread() == threading.main_thread():
             original_signal_handler = signal.signal(signal.SIGINT,
                                                     signal_handler)
@@ -101,8 +108,10 @@
         self.reconnection_delay = reconnection_delay
         self.reconnection_delay_max = reconnection_delay_max
         self.randomization_factor = randomization_factor
+        self.handle_sigint = handle_sigint
 
         engineio_options = kwargs
+        engineio_options['handle_sigint'] = handle_sigint
         engineio_logger = engineio_options.pop('engineio_logger', None)
         if engineio_logger is not None:
             engineio_options['logger'] = engineio_logger
@@ -141,8 +150,8 @@
         self.socketio_path = None
         self.sid = None
 
-        self.connected = False
-        self.namespaces = {}
+        self.connected = False  #: Indicates if the client is connected or not.
+        self.namespaces = {}  #: set of connected namespaces.
         self.handlers = {}
         self.namespace_handlers = {}
         self.callbacks = {}
@@ -423,6 +432,12 @@
     def call(self, event, data=None, namespace=None, timeout=60):
         """Emit a custom event to a client and wait for the response.
 
+        This method issues an emit with a callback and waits for the callback
+        to be invoked 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.
+
         :param event: The event name. It can be any string. The event names
                       ``'connect'``, ``'message'`` and ``'disconnect'`` are
                       reserved and should not be used.
@@ -500,9 +515,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()`` methond can be invoked to wait for the task to
+        complete.
         """
         return self.eio.start_background_task(target, *args, **kwargs)
 
@@ -612,7 +627,8 @@
         if namespace in self.handlers:
             if event in self.handlers[namespace]:
                 return self.handlers[namespace][event](*args)
-            elif '*' in self.handlers[namespace]:
+            elif event not in self.reserved_events and \
+                    '*' in self.handlers[namespace]:
                 return self.handlers[namespace]['*'](event, *args)
 
         # or else, forward the event to a namespace handler if one exists
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python-socketio-5.4.1/src/socketio/kafka_manager.py 
new/python-socketio-5.5.1/src/socketio/kafka_manager.py
--- old/python-socketio-5.4.1/src/socketio/kafka_manager.py     2021-10-14 
21:19:50.000000000 +0200
+++ new/python-socketio-5.5.1/src/socketio/kafka_manager.py     2022-01-11 
13:17:25.000000000 +0100
@@ -24,7 +24,9 @@
         server = socketio.Server(client_manager=socketio.KafkaManager(url))
 
     :param url: The connection URL for the Kafka server. For a default Kafka
-                store running on the same host, use ``kafka://``.
+                store running on the same host, use ``kafka://``. For a highly
+                available deployment of Kafka, pass a list with all the
+                connection URLs available in your cluster.
     :param channel: The channel name (topic) on which the server sends and
                     receives notifications. Must be the same in all the
                     servers.
@@ -44,10 +46,12 @@
         super(KafkaManager, self).__init__(channel=channel,
                                            write_only=write_only)
 
-        self.kafka_url = url[8:] if url != 'kafka://' else 'localhost:9092'
-        self.producer = kafka.KafkaProducer(bootstrap_servers=self.kafka_url)
+        urls = [url] if isinstance(url, str) else url
+        self.kafka_urls = [url[8:] if url != 'kafka://' else 'localhost:9092'
+                           for url in urls]
+        self.producer = kafka.KafkaProducer(bootstrap_servers=self.kafka_urls)
         self.consumer = kafka.KafkaConsumer(self.channel,
-                                            bootstrap_servers=self.kafka_url)
+                                            bootstrap_servers=self.kafka_urls)
 
     def _publish(self, data):
         self.producer.send(self.channel, value=pickle.dumps(data))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python-socketio-5.4.1/src/socketio/msgpack_packet.py 
new/python-socketio-5.5.1/src/socketio/msgpack_packet.py
--- old/python-socketio-5.4.1/src/socketio/msgpack_packet.py    2021-10-14 
21:19:50.000000000 +0200
+++ new/python-socketio-5.5.1/src/socketio/msgpack_packet.py    2022-01-11 
13:17:25.000000000 +0100
@@ -3,6 +3,8 @@
 
 
 class MsgPackPacket(packet.Packet):
+    uses_binary_events = False
+
     def encode(self):
         """Encode the packet for transmission."""
         return msgpack.dumps(self._to_dict())
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python-socketio-5.4.1/src/socketio/namespace.py 
new/python-socketio-5.5.1/src/socketio/namespace.py
--- old/python-socketio-5.4.1/src/socketio/namespace.py 2021-10-14 
21:19:50.000000000 +0200
+++ new/python-socketio-5.5.1/src/socketio/namespace.py 2022-01-11 
13:17:25.000000000 +0100
@@ -37,19 +37,20 @@
     def _set_server(self, server):
         self.server = server
 
-    def emit(self, event, data=None, room=None, skip_sid=None, namespace=None,
-             callback=None):
+    def emit(self, event, data=None, to=None, room=None, skip_sid=None,
+             namespace=None, callback=None):
         """Emit a custom event to one or more connected clients.
 
         The only difference with the :func:`socketio.Server.emit` method is
         that when the ``namespace`` argument is not given the namespace
         associated with the class is used.
         """
-        return self.server.emit(event, data=data, room=room, skip_sid=skip_sid,
+        return self.server.emit(event, data=data, to=to, room=room,
+                                skip_sid=skip_sid,
                                 namespace=namespace or self.namespace,
                                 callback=callback)
 
-    def send(self, data, room=None, skip_sid=None, namespace=None,
+    def send(self, data, to=None, room=None, skip_sid=None, namespace=None,
              callback=None):
         """Send a message to one or more connected clients.
 
@@ -57,10 +58,22 @@
         that when the ``namespace`` argument is not given the namespace
         associated with the class is used.
         """
-        return self.server.send(data, room=room, skip_sid=skip_sid,
+        return self.server.send(data, to=to, room=room, skip_sid=skip_sid,
                                 namespace=namespace or self.namespace,
                                 callback=callback)
 
+    def call(self, event, data=None, to=None, sid=None, namespace=None,
+             timeout=None):
+        """Emit a custom event to a client and wait for the response.
+
+        The only difference with the :func:`socketio.Server.call` method is
+        that when the ``namespace`` argument is not given the namespace
+        associated with the class is used.
+        """
+        return self.server.call(event, data=data, to=to, sid=sid,
+                                namespace=namespace or self.namespace,
+                                timeout=timeout)
+
     def enter_room(self, sid, room, namespace=None):
         """Enter a room.
 
@@ -170,8 +183,7 @@
                                 namespace=namespace or self.namespace,
                                 callback=callback)
 
-    def send(self, data, room=None, skip_sid=None, namespace=None,
-             callback=None):
+    def send(self, data, room=None, namespace=None, callback=None):
         """Send a message to the server.
 
         The only difference with the :func:`socketio.Client.send` method is
@@ -181,6 +193,17 @@
         return self.client.send(data, namespace=namespace or self.namespace,
                                 callback=callback)
 
+    def call(self, event, data=None, namespace=None, timeout=None):
+        """Emit a custom event to the server and wait for the response.
+
+        The only difference with the :func:`socketio.Client.call` method is
+        that when the ``namespace`` argument is not given the namespace
+        associated with the class is used.
+        """
+        return self.client.call(event, data=data,
+                                namespace=namespace or self.namespace,
+                                timeout=timeout)
+
     def disconnect(self):
         """Disconnect from the server.
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python-socketio-5.4.1/src/socketio/packet.py 
new/python-socketio-5.5.1/src/socketio/packet.py
--- old/python-socketio-5.4.1/src/socketio/packet.py    2021-10-14 
21:19:50.000000000 +0200
+++ new/python-socketio-5.5.1/src/socketio/packet.py    2022-01-11 
13:17:25.000000000 +0100
@@ -19,6 +19,7 @@
     # id: ASCII encoded, only if id is not None
     # data: JSON dump of data payload
 
+    uses_binary_events = True
     json = _json
 
     def __init__(self, packet_type=EVENT, data=None, namespace=None, id=None,
@@ -27,7 +28,9 @@
         self.data = data
         self.namespace = namespace
         self.id = id
-        if binary or (binary is None and self._data_is_binary(self.data)):
+        if self.uses_binary_events and \
+                (binary or (binary is None and self._data_is_binary(
+                    self.data))):
             if self.packet_type == EVENT:
                 self.packet_type = BINARY_EVENT
             elif self.packet_type == ACK:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python-socketio-5.4.1/src/socketio/redis_manager.py 
new/python-socketio-5.5.1/src/socketio/redis_manager.py
--- old/python-socketio-5.4.1/src/socketio/redis_manager.py     2021-10-14 
21:19:50.000000000 +0200
+++ new/python-socketio-5.5.1/src/socketio/redis_manager.py     2022-01-11 
13:17:25.000000000 +0100
@@ -27,7 +27,8 @@
         server = socketio.Server(client_manager=socketio.RedisManager(url))
 
     :param url: The connection URL for the Redis server. For a default Redis
-                store running on the same host, use ``redis://``.
+                store running on the same host, use ``redis://``.  To use an
+                SSL connection, use ``rediss://``.
     :param channel: The channel name on which the server sends and receives
                     notifications. Must be the same in all the servers.
     :param write_only: If set to ``True``, only initialize to emit events. The
@@ -69,7 +70,7 @@
     def _redis_connect(self):
         self.redis = redis.Redis.from_url(self.redis_url,
                                           **self.redis_options)
-        self.pubsub = self.redis.pubsub()
+        self.pubsub = self.redis.pubsub(ignore_subscribe_messages=True)
 
     def _publish(self, data):
         retry = True
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python-socketio-5.4.1/src/socketio/server.py 
new/python-socketio-5.5.1/src/socketio/server.py
--- old/python-socketio-5.4.1/src/socketio/server.py    2021-10-14 
21:19:50.000000000 +0200
+++ new/python-socketio-5.5.1/src/socketio/server.py    2022-01-11 
13:17:25.000000000 +0100
@@ -106,6 +106,8 @@
                             fatal errors are logged even when
                             ``engineio_logger`` is ``False``.
     """
+    reserved_events = ['connect', 'disconnect']
+
     def __init__(self, client_manager=None, logger=False, serializer='default',
                  json=None, async_handlers=True, always_connect=False,
                  **kwargs):
@@ -355,6 +357,12 @@
              timeout=60, **kwargs):
         """Emit a custom event to a client and wait for the response.
 
+        This method issues an emit with a callback and waits for the callback
+        to be invoked 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.
+
         :param event: The event name. It can be any string. The event names
                       ``'connect'``, ``'message'`` and ``'disconnect'`` are
                       reserved and should not be used.
@@ -599,9 +607,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()`` methond can be invoked to wait for the task to
+        complete.
         """
         return self.eio.start_background_task(target, *args, **kwargs)
 
@@ -735,7 +743,8 @@
         if namespace in self.handlers:
             if event in self.handlers[namespace]:
                 return self.handlers[namespace][event](*args)
-            elif '*' in self.handlers[namespace]:
+            elif event not in self.reserved_events and \
+                    '*' in self.handlers[namespace]:
                 return self.handlers[namespace]['*'](event, *args)
 
         # or else, forward the event to a namespace handler if one exists
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/python-socketio-5.4.1/tests/asyncio/test_asyncio_client.py 
new/python-socketio-5.5.1/tests/asyncio/test_asyncio_client.py
--- old/python-socketio-5.4.1/tests/asyncio/test_asyncio_client.py      
2021-10-14 21:19:50.000000000 +0200
+++ new/python-socketio-5.5.1/tests/asyncio/test_asyncio_client.py      
2022-01-11 13:17:25.000000000 +0100
@@ -838,6 +838,7 @@
         c.on('*', catchall_handler)
         _run(c._trigger_event('foo', '/', 1, '2'))
         _run(c._trigger_event('bar', '/', 1, '2', 3))
+        _run(c._trigger_event('connect', '/'))  # should not trigger
         handler.assert_called_once_with(1, '2')
         catchall_handler.assert_called_once_with('bar', 1, '2', 3)
 
@@ -891,8 +892,6 @@
             side_effect=[ValueError, exceptions.ConnectionError, None]
         )
         _run(c._handle_reconnect())
-        print(wait_for.mock.call_count)  # logging to debug #572
-        print(wait_for.mock.call_args_list)
         assert wait_for.mock.call_count == 3
         assert [x[0][1] for x in asyncio.wait_for.mock.call_args_list] == [
             1.5,
@@ -914,8 +913,6 @@
             side_effect=[ValueError, exceptions.ConnectionError, None]
         )
         _run(c._handle_reconnect())
-        print(wait_for.mock.call_count)  # logging to debug #572
-        print(wait_for.mock.call_args_list)
         assert wait_for.mock.call_count == 3
         assert [x[0][1] for x in asyncio.wait_for.mock.call_args_list] == [
             1.5,
@@ -931,15 +928,12 @@
     )
     @mock.patch('socketio.client.random.random', side_effect=[1, 0, 0.5])
     def test_handle_reconnect_max_attempts(self, random, wait_for):
-        c = asyncio_client.AsyncClient(reconnection_attempts=2)
+        c = asyncio_client.AsyncClient(reconnection_attempts=2, logger=True)
         c._reconnect_task = 'foo'
         c.connect = AsyncMock(
             side_effect=[ValueError, exceptions.ConnectionError, None]
         )
         _run(c._handle_reconnect())
-        print(c.reconnection_attempts)
-        print(wait_for.mock.call_count)  # logging to debug #572
-        print(wait_for.mock.call_args_list)
         assert wait_for.mock.call_count == 2
         assert [x[0][1] for x in asyncio.wait_for.mock.call_args_list] == [
             1.5,
@@ -954,14 +948,12 @@
     )
     @mock.patch('socketio.client.random.random', side_effect=[1, 0, 0.5])
     def test_handle_reconnect_aborted(self, random, wait_for):
-        c = asyncio_client.AsyncClient()
+        c = asyncio_client.AsyncClient(logger=True)
         c._reconnect_task = 'foo'
         c.connect = AsyncMock(
             side_effect=[ValueError, exceptions.ConnectionError, None]
         )
         _run(c._handle_reconnect())
-        print(wait_for.mock.call_count)  # logging to debug #572
-        print(wait_for.mock.call_args_list)
         assert wait_for.mock.call_count == 2
         assert [x[0][1] for x in asyncio.wait_for.mock.call_args_list] == [
             1.5,
@@ -1065,7 +1057,7 @@
             _run(c._handle_eio_message('9'))
 
     def test_eio_disconnect(self):
-        c = asyncio_client.AsyncClient()
+        c = asyncio_client.AsyncClient(reconnection=False)
         c.namespaces = {'/': '1'}
         c.connected = True
         c._trigger_event = AsyncMock()
@@ -1079,7 +1071,7 @@
         assert not c.connected
 
     def test_eio_disconnect_namespaces(self):
-        c = asyncio_client.AsyncClient()
+        c = asyncio_client.AsyncClient(reconnection=False)
         c.namespaces = {'/foo': '1', '/bar': '2'}
         c.connected = True
         c._trigger_event = AsyncMock()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/python-socketio-5.4.1/tests/asyncio/test_asyncio_namespace.py 
new/python-socketio-5.5.1/tests/asyncio/test_asyncio_namespace.py
--- old/python-socketio-5.4.1/tests/asyncio/test_asyncio_namespace.py   
2021-10-14 21:19:50.000000000 +0200
+++ new/python-socketio-5.5.1/tests/asyncio/test_asyncio_namespace.py   
2022-01-11 13:17:25.000000000 +0100
@@ -93,13 +93,14 @@
         ns._set_server(mock_server)
         _run(
             ns.emit(
-                'ev', data='data', room='room', skip_sid='skip', callback='cb'
+                'ev', data='data', to='room', skip_sid='skip', callback='cb'
             )
         )
         ns.server.emit.mock.assert_called_with(
             'ev',
             data='data',
-            room='room',
+            to='room',
+            room=None,
             skip_sid='skip',
             namespace='/foo',
             callback='cb',
@@ -117,6 +118,7 @@
         ns.server.emit.mock.assert_called_with(
             'ev',
             data='data',
+            to=None,
             room='room',
             skip_sid='skip',
             namespace='/bar',
@@ -128,10 +130,11 @@
         mock_server = mock.MagicMock()
         mock_server.send = AsyncMock()
         ns._set_server(mock_server)
-        _run(ns.send(data='data', room='room', skip_sid='skip', callback='cb'))
+        _run(ns.send(data='data', to='room', skip_sid='skip', callback='cb'))
         ns.server.send.mock.assert_called_with(
             'data',
-            room='room',
+            to='room',
+            room=None,
             skip_sid='skip',
             namespace='/foo',
             callback='cb',
@@ -147,12 +150,38 @@
         )
         ns.server.send.mock.assert_called_with(
             'data',
+            to=None,
             room='room',
             skip_sid='skip',
             namespace='/bar',
             callback='cb',
         )
 
+    def test_call(self):
+        ns = asyncio_namespace.AsyncNamespace('/foo')
+        mock_server = mock.MagicMock()
+        mock_server.call = AsyncMock()
+        ns._set_server(mock_server)
+        _run(ns.call('ev', data='data', to='sid'))
+        ns.server.call.mock.assert_called_with(
+            'ev',
+            data='data',
+            to='sid',
+            sid=None,
+            namespace='/foo',
+            timeout=None,
+        )
+        _run(ns.call('ev', data='data', sid='sid', namespace='/bar',
+                     timeout=45))
+        ns.server.call.mock.assert_called_with(
+            'ev',
+            data='data',
+            to=None,
+            sid='sid',
+            namespace='/bar',
+            timeout=45,
+        )
+
     def test_enter_room(self):
         ns = asyncio_namespace.AsyncNamespace('/foo')
         ns._set_server(mock.MagicMock())
@@ -294,6 +323,20 @@
             'data', namespace='/bar', callback='cb'
         )
 
+    def test_call_client(self):
+        ns = asyncio_namespace.AsyncClientNamespace('/foo')
+        mock_client = mock.MagicMock()
+        mock_client.call = AsyncMock()
+        ns._set_client(mock_client)
+        _run(ns.call('ev', data='data'))
+        ns.client.call.mock.assert_called_with(
+            'ev', data='data', namespace='/foo', timeout=None
+        )
+        _run(ns.call('ev', data='data', namespace='/bar', timeout=45))
+        ns.client.call.mock.assert_called_with(
+            'ev', data='data', namespace='/bar', timeout=45
+        )
+
     def test_disconnect_client(self):
         ns = asyncio_namespace.AsyncClientNamespace('/foo')
         mock_client = mock.MagicMock()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/python-socketio-5.4.1/tests/asyncio/test_asyncio_pubsub_manager.py 
new/python-socketio-5.5.1/tests/asyncio/test_asyncio_pubsub_manager.py
--- old/python-socketio-5.4.1/tests/asyncio/test_asyncio_pubsub_manager.py      
2021-10-14 21:19:50.000000000 +0200
+++ new/python-socketio-5.5.1/tests/asyncio/test_asyncio_pubsub_manager.py      
2022-01-11 13:17:25.000000000 +0100
@@ -417,7 +417,7 @@
         self.pm._handle_disconnect = AsyncMock()
         self.pm._handle_close_room = AsyncMock()
 
-        def messages():
+        async def messages():
             import pickle
 
             yield {'method': 'emit', 'value': 'foo'}
@@ -428,12 +428,10 @@
             yield pickle.dumps({'method': 'close_room', 'value': 'baz'})
             yield 'bad json'
             yield b'bad pickled'
+            raise asyncio.CancelledError()  # force the thread to exit
 
-        self.pm._listen = AsyncMock(side_effect=list(messages()))
-        try:
-            _run(self.pm._thread())
-        except StopIteration:
-            pass
+        self.pm._listen = messages
+        _run(self.pm._thread())
 
         self.pm._handle_emit.mock.assert_called_once_with(
             {'method': 'emit', 'value': 'foo'}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/python-socketio-5.4.1/tests/asyncio/test_asyncio_redis_manager.py 
new/python-socketio-5.5.1/tests/asyncio/test_asyncio_redis_manager.py
--- old/python-socketio-5.4.1/tests/asyncio/test_asyncio_redis_manager.py       
2021-10-14 21:19:50.000000000 +0200
+++ new/python-socketio-5.5.1/tests/asyncio/test_asyncio_redis_manager.py       
1970-01-01 01:00:00.000000000 +0100
@@ -1,73 +0,0 @@
-import sys
-import unittest
-
-import pytest
-
-from socketio import asyncio_redis_manager
-
-
-@unittest.skipIf(sys.version_info < (3, 5), 'only for Python 3.5+')
-class TestAsyncRedisManager(unittest.TestCase):
-    def test_default_url(self):
-        assert asyncio_redis_manager._parse_redis_url('redis://') == (
-            'localhost',
-            6379,
-            None,
-            0,
-            False,
-        )
-
-    def test_only_host_url(self):
-        assert asyncio_redis_manager._parse_redis_url(
-            'redis://redis.host'
-        ) == ('redis.host', 6379, None, 0, False)
-
-    def test_no_db_url(self):
-        assert asyncio_redis_manager._parse_redis_url(
-            'redis://redis.host:123/1'
-        ) == ('redis.host', 123, None, 1, False)
-
-    def test_no_port_url(self):
-        assert asyncio_redis_manager._parse_redis_url(
-            'redis://redis.host/1'
-        ) == ('redis.host', 6379, None, 1, False)
-
-    def test_password(self):
-        assert asyncio_redis_manager._parse_redis_url(
-            'redis://:p...@redis.host/1'
-        ) == ('redis.host', 6379, 'pw', 1, False)
-
-    def test_no_host_url(self):
-        assert asyncio_redis_manager._parse_redis_url('redis://:123/1') == (
-            'localhost',
-            123,
-            None,
-            1,
-            False,
-        )
-
-    def test_no_host_password_url(self):
-        assert asyncio_redis_manager._parse_redis_url(
-            'redis://:pw@:123/1'
-        ) == ('localhost', 123, 'pw', 1, False)
-
-    def test_bad_port_url(self):
-        with pytest.raises(ValueError):
-            asyncio_redis_manager._parse_redis_url('redis://localhost:abc/1')
-
-    def test_bad_db_url(self):
-        with pytest.raises(ValueError):
-            asyncio_redis_manager._parse_redis_url('redis://localhost:abc/z')
-
-    def test_bad_scheme_url(self):
-        with pytest.raises(ValueError):
-            asyncio_redis_manager._parse_redis_url('http://redis.host:123/1')
-
-    def test_ssl_scheme(self):
-        assert asyncio_redis_manager._parse_redis_url('rediss://') == (
-            'localhost',
-            6379,
-            None,
-            0,
-            True,
-        )
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python-socketio-5.4.1/tests/common/test_client.py 
new/python-socketio-5.5.1/tests/common/test_client.py
--- old/python-socketio-5.4.1/tests/common/test_client.py       2021-10-14 
21:19:50.000000000 +0200
+++ new/python-socketio-5.5.1/tests/common/test_client.py       2022-01-11 
13:17:25.000000000 +0100
@@ -29,6 +29,7 @@
             reconnection_delay=5,
             reconnection_delay_max=10,
             randomization_factor=0.2,
+            handle_sigint=False,
             foo='bar',
         )
         assert not c.reconnection
@@ -36,7 +37,9 @@
         assert c.reconnection_delay == 5
         assert c.reconnection_delay_max == 10
         assert c.randomization_factor == 0.2
-        engineio_client_class().assert_called_once_with(foo='bar')
+        assert not c.handle_sigint
+        engineio_client_class().assert_called_once_with(
+            foo='bar', handle_sigint=False)
         assert c.connection_url is None
         assert c.connection_headers is None
         assert c.connection_transports is None
@@ -89,7 +92,8 @@
     @mock.patch('socketio.client.Client._engineio_client_class')
     def test_engineio_logger(self, engineio_client_class):
         client.Client(engineio_logger='foo')
-        engineio_client_class().assert_called_once_with(logger='foo')
+        engineio_client_class().assert_called_once_with(
+            handle_sigint=True, logger='foo')
 
     def test_on_event(self):
         c = client.Client()
@@ -939,6 +943,7 @@
         c.on('*', catchall_handler)
         c._trigger_event('foo', '/', 1, '2')
         c._trigger_event('bar', '/', 1, '2', 3)
+        c._trigger_event('connect', '/')  # should not trigger
         handler.assert_called_once_with(1, '2')
         catchall_handler.assert_called_once_with('bar', 1, '2', 3)
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/python-socketio-5.4.1/tests/common/test_msgpack_packet.py 
new/python-socketio-5.5.1/tests/common/test_msgpack_packet.py
--- old/python-socketio-5.4.1/tests/common/test_msgpack_packet.py       
2021-10-14 21:19:50.000000000 +0200
+++ new/python-socketio-5.5.1/tests/common/test_msgpack_packet.py       
2022-01-11 13:17:25.000000000 +0100
@@ -22,3 +22,15 @@
         assert p.data == p2.data
         assert p.id == p2.id
         assert p.namespace == p2.namespace
+
+    def test_encode_binary_event_packet(self):
+        p = msgpack_packet.MsgPackPacket(packet.EVENT, data={'foo': b'bar'})
+        assert p.packet_type == packet.EVENT
+        p2 = msgpack_packet.MsgPackPacket(encoded_packet=p.encode())
+        assert p2.data == {'foo': b'bar'}
+
+    def test_encode_binary_ack_packet(self):
+        p = msgpack_packet.MsgPackPacket(packet.ACK, data={'foo': b'bar'})
+        assert p.packet_type == packet.ACK
+        p2 = msgpack_packet.MsgPackPacket(encoded_packet=p.encode())
+        assert p2.data == {'foo': b'bar'}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python-socketio-5.4.1/tests/common/test_namespace.py 
new/python-socketio-5.5.1/tests/common/test_namespace.py
--- old/python-socketio-5.4.1/tests/common/test_namespace.py    2021-10-14 
21:19:50.000000000 +0200
+++ new/python-socketio-5.5.1/tests/common/test_namespace.py    2022-01-11 
13:17:25.000000000 +0100
@@ -56,11 +56,12 @@
     def test_emit(self):
         ns = namespace.Namespace('/foo')
         ns._set_server(mock.MagicMock())
-        ns.emit('ev', data='data', room='room', skip_sid='skip', callback='cb')
+        ns.emit('ev', data='data', to='room', skip_sid='skip', callback='cb')
         ns.server.emit.assert_called_with(
             'ev',
             data='data',
-            room='room',
+            to='room',
+            room=None,
             skip_sid='skip',
             namespace='/foo',
             callback='cb',
@@ -76,6 +77,7 @@
         ns.server.emit.assert_called_with(
             'ev',
             data='data',
+            to=None,
             room='room',
             skip_sid='skip',
             namespace='/bar',
@@ -85,10 +87,11 @@
     def test_send(self):
         ns = namespace.Namespace('/foo')
         ns._set_server(mock.MagicMock())
-        ns.send(data='data', room='room', skip_sid='skip', callback='cb')
+        ns.send(data='data', to='room', skip_sid='skip', callback='cb')
         ns.server.send.assert_called_with(
             'data',
-            room='room',
+            to='room',
+            room=None,
             skip_sid='skip',
             namespace='/foo',
             callback='cb',
@@ -102,12 +105,41 @@
         )
         ns.server.send.assert_called_with(
             'data',
+            to=None,
             room='room',
             skip_sid='skip',
             namespace='/bar',
             callback='cb',
         )
 
+    def test_call(self):
+        ns = namespace.Namespace('/foo')
+        ns._set_server(mock.MagicMock())
+        ns.call('ev', data='data', to='sid')
+        ns.server.call.assert_called_with(
+            'ev',
+            data='data',
+            to='sid',
+            sid=None,
+            namespace='/foo',
+            timeout=None,
+        )
+        ns.call(
+            'ev',
+            data='data',
+            sid='sid',
+            namespace='/bar',
+            timeout=45,
+        )
+        ns.server.call.assert_called_with(
+            'ev',
+            data='data',
+            to=None,
+            sid='sid',
+            namespace='/bar',
+            timeout=45,
+        )
+
     def test_enter_room(self):
         ns = namespace.Namespace('/foo')
         ns._set_server(mock.MagicMock())
@@ -200,6 +232,17 @@
             'data', namespace='/bar', callback='cb'
         )
 
+    def test_call_client(self):
+        ns = namespace.ClientNamespace('/foo')
+        ns._set_client(mock.MagicMock())
+        ns.call('ev', data='data')
+        ns.client.call.assert_called_with(
+            'ev', data='data', namespace='/foo', timeout=None)
+        ns.call('ev', data='data', namespace='/bar', timeout=45)
+        ns.client.call.assert_called_with(
+            'ev', data='data', namespace='/bar', timeout=45
+        )
+
     def test_disconnect_client(self):
         ns = namespace.ClientNamespace('/foo')
         ns._set_client(mock.MagicMock())
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python-socketio-5.4.1/tox.ini 
new/python-socketio-5.5.1/tox.ini
--- old/python-socketio-5.4.1/tox.ini   2021-10-14 21:19:50.000000000 +0200
+++ new/python-socketio-5.5.1/tox.ini   2022-01-11 13:17:25.000000000 +0100
@@ -23,7 +23,7 @@
 deps=
     flake8
 commands=
-    flake8 --exclude=".*" --ignore=W503,E402,E722 src/socketio tests
+    flake8 --exclude=".*" --ignore=W503,E402,E722 src/socketio tests examples
 
 [testenv:docs]
 changedir=docs

Reply via email to