python-socketio 5.16.0__tar.gz → 5.16.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (94) hide show
  1. {python_socketio-5.16.0/src/python_socketio.egg-info → python_socketio-5.16.2}/PKG-INFO +3 -2
  2. python_socketio-5.16.2/docs/api.rst +12 -0
  3. python_socketio-5.16.2/docs/api_client.rst +11 -0
  4. python_socketio-5.16.2/docs/api_manager.rst +39 -0
  5. python_socketio-5.16.2/docs/api_middleware.rst +12 -0
  6. python_socketio-5.16.2/docs/api_namespace.rst +19 -0
  7. python_socketio-5.16.2/docs/api_server.rst +14 -0
  8. python_socketio-5.16.2/docs/api_simpleclient.rst +11 -0
  9. {python_socketio-5.16.0 → python_socketio-5.16.2}/docs/client.rst +1 -1
  10. {python_socketio-5.16.0 → python_socketio-5.16.2}/docs/conf.py +2 -8
  11. {python_socketio-5.16.0 → python_socketio-5.16.2}/docs/index.rst +1 -1
  12. {python_socketio-5.16.0 → python_socketio-5.16.2}/docs/server.rst +1 -1
  13. {python_socketio-5.16.0 → python_socketio-5.16.2}/pyproject.toml +3 -2
  14. {python_socketio-5.16.0 → python_socketio-5.16.2/src/python_socketio.egg-info}/PKG-INFO +3 -2
  15. {python_socketio-5.16.0 → python_socketio-5.16.2}/src/python_socketio.egg-info/SOURCES.txt +6 -0
  16. {python_socketio-5.16.0 → python_socketio-5.16.2}/src/python_socketio.egg-info/requires.txt +2 -1
  17. {python_socketio-5.16.0 → python_socketio-5.16.2}/src/socketio/admin.py +6 -0
  18. {python_socketio-5.16.0 → python_socketio-5.16.2}/src/socketio/async_admin.py +6 -3
  19. {python_socketio-5.16.0 → python_socketio-5.16.2}/src/socketio/async_aiopika_manager.py +15 -5
  20. {python_socketio-5.16.0 → python_socketio-5.16.2}/src/socketio/async_client.py +3 -2
  21. {python_socketio-5.16.0 → python_socketio-5.16.2}/src/socketio/async_pubsub_manager.py +18 -4
  22. {python_socketio-5.16.0 → python_socketio-5.16.2}/src/socketio/async_redis_manager.py +15 -5
  23. {python_socketio-5.16.0 → python_socketio-5.16.2}/src/socketio/async_server.py +8 -2
  24. {python_socketio-5.16.0 → python_socketio-5.16.2}/src/socketio/base_manager.py +3 -0
  25. {python_socketio-5.16.0 → python_socketio-5.16.2}/src/socketio/client.py +3 -2
  26. {python_socketio-5.16.0 → python_socketio-5.16.2}/src/socketio/kafka_manager.py +15 -5
  27. {python_socketio-5.16.0 → python_socketio-5.16.2}/src/socketio/kombu_manager.py +15 -5
  28. {python_socketio-5.16.0 → python_socketio-5.16.2}/src/socketio/pubsub_manager.py +18 -4
  29. {python_socketio-5.16.0 → python_socketio-5.16.2}/src/socketio/redis_manager.py +15 -5
  30. {python_socketio-5.16.0 → python_socketio-5.16.2}/src/socketio/server.py +8 -2
  31. {python_socketio-5.16.0 → python_socketio-5.16.2}/src/socketio/zmq_manager.py +17 -9
  32. {python_socketio-5.16.0 → python_socketio-5.16.2}/tests/async/test_pubsub_manager.py +13 -0
  33. {python_socketio-5.16.0 → python_socketio-5.16.2}/tests/async/test_redis_manager.py +14 -1
  34. {python_socketio-5.16.0 → python_socketio-5.16.2}/tests/async/test_server.py +32 -0
  35. {python_socketio-5.16.0 → python_socketio-5.16.2}/tests/common/test_pubsub_manager.py +13 -0
  36. {python_socketio-5.16.0 → python_socketio-5.16.2}/tests/common/test_redis_manager.py +14 -1
  37. {python_socketio-5.16.0 → python_socketio-5.16.2}/tests/common/test_server.py +29 -0
  38. {python_socketio-5.16.0 → python_socketio-5.16.2}/tox.ini +2 -14
  39. python_socketio-5.16.0/docs/api.rst +0 -91
  40. {python_socketio-5.16.0 → python_socketio-5.16.2}/LICENSE +0 -0
  41. {python_socketio-5.16.0 → python_socketio-5.16.2}/MANIFEST.in +0 -0
  42. {python_socketio-5.16.0 → python_socketio-5.16.2}/README.md +0 -0
  43. {python_socketio-5.16.0 → python_socketio-5.16.2}/docs/Makefile +0 -0
  44. {python_socketio-5.16.0 → python_socketio-5.16.2}/docs/_static/README.md +0 -0
  45. {python_socketio-5.16.0 → python_socketio-5.16.2}/docs/_static/custom.css +0 -0
  46. {python_socketio-5.16.0 → python_socketio-5.16.2}/docs/intro.rst +0 -0
  47. {python_socketio-5.16.0 → python_socketio-5.16.2}/docs/make.bat +0 -0
  48. {python_socketio-5.16.0 → python_socketio-5.16.2}/setup.cfg +0 -0
  49. {python_socketio-5.16.0 → python_socketio-5.16.2}/src/python_socketio.egg-info/dependency_links.txt +0 -0
  50. {python_socketio-5.16.0 → python_socketio-5.16.2}/src/python_socketio.egg-info/not-zip-safe +0 -0
  51. {python_socketio-5.16.0 → python_socketio-5.16.2}/src/python_socketio.egg-info/top_level.txt +0 -0
  52. {python_socketio-5.16.0 → python_socketio-5.16.2}/src/socketio/__init__.py +0 -0
  53. {python_socketio-5.16.0 → python_socketio-5.16.2}/src/socketio/asgi.py +0 -0
  54. {python_socketio-5.16.0 → python_socketio-5.16.2}/src/socketio/async_manager.py +0 -0
  55. {python_socketio-5.16.0 → python_socketio-5.16.2}/src/socketio/async_namespace.py +0 -0
  56. {python_socketio-5.16.0 → python_socketio-5.16.2}/src/socketio/async_simple_client.py +0 -0
  57. {python_socketio-5.16.0 → python_socketio-5.16.2}/src/socketio/base_client.py +0 -0
  58. {python_socketio-5.16.0 → python_socketio-5.16.2}/src/socketio/base_namespace.py +0 -0
  59. {python_socketio-5.16.0 → python_socketio-5.16.2}/src/socketio/base_server.py +0 -0
  60. {python_socketio-5.16.0 → python_socketio-5.16.2}/src/socketio/exceptions.py +0 -0
  61. {python_socketio-5.16.0 → python_socketio-5.16.2}/src/socketio/manager.py +0 -0
  62. {python_socketio-5.16.0 → python_socketio-5.16.2}/src/socketio/middleware.py +0 -0
  63. {python_socketio-5.16.0 → python_socketio-5.16.2}/src/socketio/msgpack_packet.py +0 -0
  64. {python_socketio-5.16.0 → python_socketio-5.16.2}/src/socketio/namespace.py +0 -0
  65. {python_socketio-5.16.0 → python_socketio-5.16.2}/src/socketio/packet.py +0 -0
  66. {python_socketio-5.16.0 → python_socketio-5.16.2}/src/socketio/simple_client.py +0 -0
  67. {python_socketio-5.16.0 → python_socketio-5.16.2}/src/socketio/tornado.py +0 -0
  68. {python_socketio-5.16.0 → python_socketio-5.16.2}/tests/__init__.py +0 -0
  69. {python_socketio-5.16.0 → python_socketio-5.16.2}/tests/async/__init__.py +0 -0
  70. {python_socketio-5.16.0 → python_socketio-5.16.2}/tests/async/test_admin.py +0 -0
  71. {python_socketio-5.16.0 → python_socketio-5.16.2}/tests/async/test_client.py +0 -0
  72. {python_socketio-5.16.0 → python_socketio-5.16.2}/tests/async/test_manager.py +0 -0
  73. {python_socketio-5.16.0 → python_socketio-5.16.2}/tests/async/test_namespace.py +0 -0
  74. {python_socketio-5.16.0 → python_socketio-5.16.2}/tests/async/test_simple_client.py +0 -0
  75. {python_socketio-5.16.0 → python_socketio-5.16.2}/tests/asyncio_web_server.py +0 -0
  76. {python_socketio-5.16.0 → python_socketio-5.16.2}/tests/common/__init__.py +0 -0
  77. {python_socketio-5.16.0 → python_socketio-5.16.2}/tests/common/test_admin.py +0 -0
  78. {python_socketio-5.16.0 → python_socketio-5.16.2}/tests/common/test_client.py +0 -0
  79. {python_socketio-5.16.0 → python_socketio-5.16.2}/tests/common/test_manager.py +0 -0
  80. {python_socketio-5.16.0 → python_socketio-5.16.2}/tests/common/test_middleware.py +0 -0
  81. {python_socketio-5.16.0 → python_socketio-5.16.2}/tests/common/test_msgpack_packet.py +0 -0
  82. {python_socketio-5.16.0 → python_socketio-5.16.2}/tests/common/test_namespace.py +0 -0
  83. {python_socketio-5.16.0 → python_socketio-5.16.2}/tests/common/test_packet.py +0 -0
  84. {python_socketio-5.16.0 → python_socketio-5.16.2}/tests/common/test_simple_client.py +0 -0
  85. {python_socketio-5.16.0 → python_socketio-5.16.2}/tests/performance/README.md +0 -0
  86. {python_socketio-5.16.0 → python_socketio-5.16.2}/tests/performance/binary_packet.py +0 -0
  87. {python_socketio-5.16.0 → python_socketio-5.16.2}/tests/performance/json_packet.py +0 -0
  88. {python_socketio-5.16.0 → python_socketio-5.16.2}/tests/performance/namespace_packet.py +0 -0
  89. {python_socketio-5.16.0 → python_socketio-5.16.2}/tests/performance/run.sh +0 -0
  90. {python_socketio-5.16.0 → python_socketio-5.16.2}/tests/performance/server_receive.py +0 -0
  91. {python_socketio-5.16.0 → python_socketio-5.16.2}/tests/performance/server_send.py +0 -0
  92. {python_socketio-5.16.0 → python_socketio-5.16.2}/tests/performance/server_send_broadcast.py +0 -0
  93. {python_socketio-5.16.0 → python_socketio-5.16.2}/tests/performance/text_packet.py +0 -0
  94. {python_socketio-5.16.0 → python_socketio-5.16.2}/tests/web_server.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-socketio
3
- Version: 5.16.0
3
+ Version: 5.16.2
4
4
  Summary: Socket.IO server and client for Python
5
5
  Author-email: Miguel Grinberg <miguel.grinberg@gmail.com>
6
6
  License: MIT
@@ -14,7 +14,7 @@ Requires-Python: >=3.8
14
14
  Description-Content-Type: text/markdown
15
15
  License-File: LICENSE
16
16
  Requires-Dist: bidict>=0.21.0
17
- Requires-Dist: python-engineio>=4.11.0
17
+ Requires-Dist: python-engineio>=4.13.2
18
18
  Provides-Extra: client
19
19
  Requires-Dist: requests>=2.21.0; extra == "client"
20
20
  Requires-Dist: websocket-client>=0.54.0; extra == "client"
@@ -24,6 +24,7 @@ Provides-Extra: dev
24
24
  Requires-Dist: tox; extra == "dev"
25
25
  Provides-Extra: docs
26
26
  Requires-Dist: sphinx; extra == "docs"
27
+ Requires-Dist: furo; extra == "docs"
27
28
  Dynamic: license-file
28
29
 
29
30
  python-socketio
@@ -0,0 +1,12 @@
1
+ API Reference
2
+ =============
3
+
4
+ .. toctree::
5
+ :maxdepth: 2
6
+
7
+ api_simpleclient
8
+ api_client
9
+ api_server
10
+ api_middleware
11
+ api_namespace
12
+ api_manager
@@ -0,0 +1,11 @@
1
+ Clients
2
+ -------
3
+
4
+ .. autoclass:: socketio.Client
5
+ :members:
6
+ :inherited-members:
7
+
8
+ .. autoclass:: socketio.AsyncClient
9
+ :members:
10
+ :inherited-members:
11
+
@@ -0,0 +1,39 @@
1
+ Managers
2
+ --------
3
+
4
+ .. autoclass:: socketio.Manager
5
+ :members:
6
+ :inherited-members:
7
+
8
+ .. autoclass:: socketio.PubSubManager
9
+ :members:
10
+ :inherited-members:
11
+
12
+ .. autoclass:: socketio.KombuManager
13
+ :members:
14
+ :inherited-members:
15
+
16
+ .. autoclass:: socketio.RedisManager
17
+ :members:
18
+ :inherited-members:
19
+
20
+ .. autoclass:: socketio.KafkaManager
21
+ :members:
22
+ :inherited-members:
23
+
24
+ .. autoclass:: socketio.ZmqManager
25
+ :members:
26
+ :inherited-members:
27
+
28
+ .. autoclass:: socketio.AsyncManager
29
+ :members:
30
+ :inherited-members:
31
+
32
+ .. autoclass:: socketio.AsyncRedisManager
33
+ :members:
34
+ :inherited-members:
35
+
36
+ .. autoclass:: socketio.AsyncAioPikaManager
37
+ :members:
38
+ :inherited-members:
39
+
@@ -0,0 +1,12 @@
1
+ Middlewares
2
+ -----------
3
+
4
+ .. autoclass:: socketio.WSGIApp
5
+ :members:
6
+
7
+ .. autoclass:: socketio.ASGIApp
8
+ :members:
9
+
10
+ .. autoclass:: socketio.Middleware
11
+ :members:
12
+
@@ -0,0 +1,19 @@
1
+ Namespaces
2
+ ----------
3
+
4
+ .. autoclass:: socketio.ClientNamespace
5
+ :members:
6
+ :inherited-members:
7
+
8
+ .. autoclass:: socketio.Namespace
9
+ :members:
10
+ :inherited-members:
11
+
12
+ .. autoclass:: socketio.AsyncClientNamespace
13
+ :members:
14
+ :inherited-members:
15
+
16
+ .. autoclass:: socketio.AsyncNamespace
17
+ :members:
18
+ :inherited-members:
19
+
@@ -0,0 +1,14 @@
1
+ Servers
2
+ -------
3
+
4
+ .. autoclass:: socketio.Server
5
+ :members:
6
+ :inherited-members:
7
+
8
+ .. autoclass:: socketio.AsyncServer
9
+ :members:
10
+ :inherited-members:
11
+
12
+ .. autoclass:: socketio.exceptions.ConnectionRefusedError
13
+ :members:
14
+
@@ -0,0 +1,11 @@
1
+ Simple Clients
2
+ --------------
3
+
4
+ .. autoclass:: socketio.SimpleClient
5
+ :members:
6
+ :inherited-members:
7
+
8
+ .. autoclass:: socketio.AsyncSimpleClient
9
+ :members:
10
+ :inherited-members:
11
+
@@ -280,7 +280,7 @@ remaining arguments are the same as for a regular event handler.
280
280
  The ``connect`` and ``disconnect`` events have to be defined explicitly and are
281
281
  not invoked on a catch-all event handler.
282
282
 
283
- Similarily, a "catch-all" namespace handler is invoked for any connected
283
+ Similarly, a "catch-all" namespace handler is invoked for any connected
284
284
  namespaces that do not have an explicitly defined event handler. As with
285
285
  catch-all events, ``'*'`` is used in place of a namespace::
286
286
 
@@ -77,20 +77,14 @@ pygments_style = None
77
77
  # The theme to use for HTML and HTML Help pages. See the documentation for
78
78
  # a list of builtin themes.
79
79
  #
80
- html_theme = 'alabaster'
80
+ html_theme = 'furo'
81
+ html_title = 'python-socketio'
81
82
 
82
83
  # Theme options are theme-specific and customize the look and feel of a theme
83
84
  # further. For a list of options available for each theme, see the
84
85
  # documentation.
85
86
  #
86
87
  html_theme_options = {
87
- 'github_user': 'miguelgrinberg',
88
- 'github_repo': 'python-socketio',
89
- 'github_banner': True,
90
- 'github_button': True,
91
- 'github_type': 'star',
92
- 'fixed_sidebar': True,
93
-
94
88
  }
95
89
 
96
90
  # Add any paths that contain custom static files (such as style sheets) here,
@@ -10,7 +10,7 @@ This projects implements Socket.IO clients and servers that can run standalone
10
10
  or integrated with a variety of Python web frameworks.
11
11
 
12
12
  .. toctree::
13
- :maxdepth: 3
13
+ :maxdepth: 2
14
14
 
15
15
  intro
16
16
  client
@@ -492,7 +492,7 @@ information.
492
492
  Catch-All Namespaces
493
493
  ~~~~~~~~~~~~~~~~~~~~
494
494
 
495
- Similarily to catch-all event handlers, a "catch-all" namespace can be used
495
+ Similarly to catch-all event handlers, a "catch-all" namespace can be used
496
496
  when defining event handlers for any connected namespaces that do not have an
497
497
  explicitly defined event handler. As with catch-all events, ``'*'`` is used in
498
498
  place of a namespace::
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "python-socketio"
3
- version = "5.16.0"
3
+ version = "5.16.2"
4
4
  license = {text = "MIT"}
5
5
  authors = [
6
6
  { name = "Miguel Grinberg", email = "miguel.grinberg@gmail.com" },
@@ -15,7 +15,7 @@ classifiers = [
15
15
  requires-python = ">=3.8"
16
16
  dependencies = [
17
17
  "bidict >= 0.21.0",
18
- "python-engineio >= 4.11.0",
18
+ "python-engineio >= 4.13.2",
19
19
  ]
20
20
 
21
21
  [project.readme]
@@ -39,6 +39,7 @@ dev = [
39
39
  ]
40
40
  docs = [
41
41
  "sphinx",
42
+ "furo",
42
43
  ]
43
44
 
44
45
  [tool.setuptools]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-socketio
3
- Version: 5.16.0
3
+ Version: 5.16.2
4
4
  Summary: Socket.IO server and client for Python
5
5
  Author-email: Miguel Grinberg <miguel.grinberg@gmail.com>
6
6
  License: MIT
@@ -14,7 +14,7 @@ Requires-Python: >=3.8
14
14
  Description-Content-Type: text/markdown
15
15
  License-File: LICENSE
16
16
  Requires-Dist: bidict>=0.21.0
17
- Requires-Dist: python-engineio>=4.11.0
17
+ Requires-Dist: python-engineio>=4.13.2
18
18
  Provides-Extra: client
19
19
  Requires-Dist: requests>=2.21.0; extra == "client"
20
20
  Requires-Dist: websocket-client>=0.54.0; extra == "client"
@@ -24,6 +24,7 @@ Provides-Extra: dev
24
24
  Requires-Dist: tox; extra == "dev"
25
25
  Provides-Extra: docs
26
26
  Requires-Dist: sphinx; extra == "docs"
27
+ Requires-Dist: furo; extra == "docs"
27
28
  Dynamic: license-file
28
29
 
29
30
  python-socketio
@@ -5,6 +5,12 @@ pyproject.toml
5
5
  tox.ini
6
6
  docs/Makefile
7
7
  docs/api.rst
8
+ docs/api_client.rst
9
+ docs/api_manager.rst
10
+ docs/api_middleware.rst
11
+ docs/api_namespace.rst
12
+ docs/api_server.rst
13
+ docs/api_simpleclient.rst
8
14
  docs/client.rst
9
15
  docs/conf.py
10
16
  docs/index.rst
@@ -1,5 +1,5 @@
1
1
  bidict>=0.21.0
2
- python-engineio>=4.11.0
2
+ python-engineio>=4.13.2
3
3
 
4
4
  [asyncio_client]
5
5
  aiohttp>=3.4
@@ -13,3 +13,4 @@ tox
13
13
 
14
14
  [docs]
15
15
  sphinx
16
+ furo
@@ -194,6 +194,8 @@ class InstrumentedServer:
194
194
  if self.stats_task: # pragma: no branch
195
195
  self.stop_stats_event.set()
196
196
  self.stats_task.join()
197
+ self.stop_stats_event.clear()
198
+ self.stats_task = None
197
199
 
198
200
  def _trigger_event(self, event, namespace, *args):
199
201
  t = time.time()
@@ -206,6 +208,9 @@ class InstrumentedServer:
206
208
  serialized_socket,
207
209
  datetime.fromtimestamp(t, timezone.utc).isoformat(),
208
210
  ), namespace=self.admin_namespace)
211
+ if not self.sio.eio._get_socket(eio_sid).upgraded:
212
+ self.sio.start_background_task(
213
+ self._check_for_upgrade, eio_sid, sid, namespace)
209
214
  elif event == 'disconnect':
210
215
  del self.sio.manager._timestamps[sid]
211
216
  reason = args[1]
@@ -283,6 +288,7 @@ class InstrumentedServer:
283
288
  def _handle_eio_connect(self, eio_sid, environ):
284
289
  if self.stop_stats_event is None:
285
290
  self.stop_stats_event = self.sio.eio.create_event()
291
+ if self.stats_task is None:
286
292
  self.stats_task = self.sio.start_background_task(
287
293
  self._emit_server_stats)
288
294
 
@@ -157,9 +157,6 @@ class InstrumentedAsyncServer:
157
157
  namespace=self.admin_namespace)
158
158
 
159
159
  self.sio.start_background_task(config, sid)
160
- self.stop_stats_event = self.sio.eio.create_event()
161
- self.stats_task = self.sio.start_background_task(
162
- self._emit_server_stats)
163
160
 
164
161
  async def admin_emit(self, _, namespace, room_filter, event, *data):
165
162
  await self.sio.emit(event, data, to=room_filter, namespace=namespace)
@@ -183,6 +180,8 @@ class InstrumentedAsyncServer:
183
180
  if self.stats_task: # pragma: no branch
184
181
  self.stop_stats_event.set()
185
182
  await asyncio.gather(self.stats_task)
183
+ self.stats_task = None
184
+ self.stop_stats_event.clear()
186
185
 
187
186
  async def _trigger_event(self, event, namespace, *args):
188
187
  t = time.time()
@@ -195,6 +194,9 @@ class InstrumentedAsyncServer:
195
194
  serialized_socket,
196
195
  datetime.fromtimestamp(t, timezone.utc).isoformat(),
197
196
  ), namespace=self.admin_namespace)
197
+ if not self.sio.eio._get_socket(eio_sid).upgraded:
198
+ self.sio.start_background_task(
199
+ self._check_for_upgrade, eio_sid, sid, namespace)
198
200
  elif event == 'disconnect':
199
201
  del self.sio.manager._timestamps[sid]
200
202
  reason = args[1]
@@ -273,6 +275,7 @@ class InstrumentedAsyncServer:
273
275
  async def _handle_eio_connect(self, eio_sid, environ):
274
276
  if self.stop_stats_event is None:
275
277
  self.stop_stats_event = self.sio.eio.create_event()
278
+ if self.stats_task is None:
276
279
  self.stats_task = self.sio.start_background_task(
277
280
  self._emit_server_stats)
278
281
 
@@ -1,6 +1,5 @@
1
1
  import asyncio
2
2
 
3
- from engineio import json
4
3
  from .async_pubsub_manager import AsyncPubSubManager
5
4
 
6
5
  try:
@@ -32,18 +31,29 @@ class AsyncAioPikaManager(AsyncPubSubManager): # pragma: no cover
32
31
  in rabbitmq
33
32
  :param write_only: If set to ``True``, only initialize to emit events. The
34
33
  default of ``False`` initializes the class for emitting
35
- and receiving.
34
+ and receiving. A write-only instance can be used
35
+ independently of the server to emit to clients from an
36
+ external process.
37
+ :param logger: a custom logger to log it. If not given, the server logger
38
+ is used.
39
+ :param json: An alternative JSON module to use for encoding and decoding
40
+ packets. Custom json modules must have ``dumps`` and ``loads``
41
+ functions that are compatible with the standard library
42
+ versions. This setting is only used when ``write_only`` is set
43
+ to ``True``. Otherwise the JSON module configured in the
44
+ server is used.
36
45
  """
37
46
 
38
47
  name = 'asyncaiopika'
39
48
 
40
49
  def __init__(self, url='amqp://guest:guest@localhost:5672//',
41
- channel='socketio', write_only=False, logger=None):
50
+ channel='socketio', write_only=False, logger=None, json=None):
42
51
  if aio_pika is None:
43
52
  raise RuntimeError('aio_pika package is not installed '
44
53
  '(Run "pip install aio_pika" in your '
45
54
  'virtualenv).')
46
- super().__init__(channel=channel, write_only=write_only, logger=logger)
55
+ super().__init__(channel=channel, write_only=write_only, logger=logger,
56
+ json=json)
47
57
  self.url = url
48
58
  self._lock = asyncio.Lock()
49
59
  self.publisher_connection = None
@@ -82,7 +92,7 @@ class AsyncAioPikaManager(AsyncPubSubManager): # pragma: no cover
82
92
  try:
83
93
  await self.publisher_exchange.publish(
84
94
  aio_pika.Message(
85
- body=json.dumps(data).encode(),
95
+ body=self.json.dumps(data).encode(),
86
96
  delivery_mode=aio_pika.DeliveryMode.PERSISTENT
87
97
  ), routing_key='*',
88
98
  )
@@ -37,10 +37,11 @@ class AsyncClient(base_client.BaseClient):
37
37
  use. To disable logging set to ``False``. The default is
38
38
  ``False``. Note that fatal errors are logged even when
39
39
  ``logger`` is ``False``.
40
- :param json: An alternative json module to use for encoding and decoding
40
+ :param json: An alternative JSON module to use for encoding and decoding
41
41
  packets. Custom json modules must have ``dumps`` and ``loads``
42
42
  functions that are compatible with the standard library
43
- versions.
43
+ versions. This is a process-wide setting, all instantiated
44
+ servers and clients must use the same JSON module.
44
45
  :param handle_sigint: Set to ``True`` to automatically handle disconnection
45
46
  when the process is interrupted, or to ``False`` to
46
47
  leave interrupt handling to the calling application.
@@ -3,8 +3,6 @@ import base64
3
3
  from functools import partial
4
4
  import uuid
5
5
 
6
- from engineio import json
7
-
8
6
  from .async_manager import AsyncManager
9
7
  from .packet import Packet
10
8
 
@@ -22,15 +20,31 @@ class AsyncPubSubManager(AsyncManager):
22
20
 
23
21
  :param channel: The channel name on which the server sends and receives
24
22
  notifications.
23
+ :param write_only: If set to ``True``, only initialize to emit events. The
24
+ default of ``False`` initializes the class for emitting
25
+ and receiving. A write-only instance can be used
26
+ independently of the server to emit to clients from an
27
+ external process.
28
+ :param logger: a custom logger to log it. If not given, the server logger
29
+ is used.
30
+ :param json: An alternative JSON module to use for encoding and decoding
31
+ packets. Custom json modules must have ``dumps`` and ``loads``
32
+ functions that are compatible with the standard library
33
+ versions. This setting is only used when ``write_only`` is set
34
+ to ``True``. Otherwise the JSON module configured in the
35
+ server is used.
25
36
  """
26
37
  name = 'asyncpubsub'
27
38
 
28
- def __init__(self, channel='socketio', write_only=False, logger=None):
39
+ def __init__(self, channel='socketio', write_only=False, logger=None,
40
+ json=None):
29
41
  super().__init__()
30
42
  self.channel = channel
31
43
  self.write_only = write_only
32
44
  self.host_id = uuid.uuid4().hex
33
45
  self.logger = logger
46
+ if json is not None:
47
+ self.json = json
34
48
 
35
49
  def initialize(self):
36
50
  super().initialize()
@@ -221,7 +235,7 @@ class AsyncPubSubManager(AsyncManager):
221
235
  data = message
222
236
  else:
223
237
  try:
224
- data = json.loads(message)
238
+ data = self.json.loads(message)
225
239
  except:
226
240
  pass
227
241
  if data and 'method' in data:
@@ -19,7 +19,6 @@ except ImportError: # pragma: no cover
19
19
  aiovalkey = None
20
20
  ValkeyError = None
21
21
 
22
- from engineio import json
23
22
  from .async_pubsub_manager import AsyncPubSubManager
24
23
  from .redis_manager import parse_redis_sentinel_url
25
24
 
@@ -47,18 +46,29 @@ class AsyncRedisManager(AsyncPubSubManager):
47
46
  notifications. Must be the same in all the servers.
48
47
  :param write_only: If set to ``True``, only initialize to emit events. The
49
48
  default of ``False`` initializes the class for emitting
50
- and receiving.
49
+ and receiving. A write-only instance can be used
50
+ independently of the server to emit to clients from an
51
+ external process.
52
+ :param logger: a custom logger to log it. If not given, the server logger
53
+ is used.
54
+ :param json: An alternative JSON module to use for encoding and decoding
55
+ packets. Custom json modules must have ``dumps`` and ``loads``
56
+ functions that are compatible with the standard library
57
+ versions. This setting is only used when ``write_only`` is set
58
+ to ``True``. Otherwise the JSON module configured in the
59
+ server is used.
51
60
  :param redis_options: additional keyword arguments to be passed to
52
61
  ``Redis.from_url()`` or ``Sentinel()``.
53
62
  """
54
63
  name = 'aioredis'
55
64
 
56
65
  def __init__(self, url='redis://localhost:6379/0', channel='socketio',
57
- write_only=False, logger=None, redis_options=None):
66
+ write_only=False, logger=None, json=None, redis_options=None):
58
67
  if aioredis and \
59
68
  not hasattr(aioredis.Redis, 'from_url'): # pragma: no cover
60
69
  raise RuntimeError('Version 2 of aioredis package is required.')
61
- super().__init__(channel=channel, write_only=write_only, logger=logger)
70
+ super().__init__(channel=channel, write_only=write_only, logger=logger,
71
+ json=json)
62
72
  self.redis_url = url
63
73
  self.redis_options = redis_options or {}
64
74
  self.connected = False
@@ -117,7 +127,7 @@ class AsyncRedisManager(AsyncPubSubManager):
117
127
  if not self.connected:
118
128
  self._redis_connect()
119
129
  return await self.redis.publish(
120
- self.channel, json.dumps(data))
130
+ self.channel, self.json.dumps(data))
121
131
  except error as exc:
122
132
  if retries_left > 0:
123
133
  self._get_logger().error(
@@ -28,10 +28,11 @@ class AsyncServer(base_server.BaseServer):
28
28
  :param logger: To enable logging set to ``True`` or pass a logger object to
29
29
  use. To disable logging set to ``False``. Note that fatal
30
30
  errors are logged even when ``logger`` is ``False``.
31
- :param json: An alternative json module to use for encoding and decoding
31
+ :param json: An alternative JSON module to use for encoding and decoding
32
32
  packets. Custom json modules must have ``dumps`` and ``loads``
33
33
  functions that are compatible with the standard library
34
- versions.
34
+ versions. This is a process-wide setting, all instantiated
35
+ servers and clients must use the same JSON module.
35
36
  :param async_handlers: If set to ``True``, event handlers for a client are
36
37
  executed in separate threads. To run handlers for a
37
38
  client synchronously, set to ``False``. The default
@@ -426,6 +427,8 @@ class AsyncServer(base_server.BaseServer):
426
427
  if delete_it:
427
428
  self.logger.info('Disconnecting %s [%s]', sid, namespace)
428
429
  eio_sid = self.manager.pre_disconnect(sid, namespace=namespace)
430
+ if eio_sid in self._binary_packet:
431
+ del self._binary_packet[eio_sid]
429
432
  await self._send_packet(eio_sid, self.packet_class(
430
433
  packet.DISCONNECT, namespace=namespace))
431
434
  await self._trigger_event('disconnect', namespace, sid,
@@ -701,6 +704,9 @@ class AsyncServer(base_server.BaseServer):
701
704
  pkt.data)
702
705
  elif pkt.packet_type == packet.BINARY_EVENT or \
703
706
  pkt.packet_type == packet.BINARY_ACK:
707
+ if not self.manager.sid_from_eio_sid(eio_sid,
708
+ pkt.namespace or '/'):
709
+ raise ValueError('Unexpected binary packet')
704
710
  self._binary_packet[eio_sid] = pkt
705
711
  elif pkt.packet_type == packet.CONNECT_ERROR:
706
712
  raise ValueError('Unexpected CONNECT_ERROR packet.')
@@ -1,5 +1,6 @@
1
1
  import itertools
2
2
  import logging
3
+ import json
3
4
 
4
5
  from bidict import bidict, ValueDuplicationError
5
6
 
@@ -14,9 +15,11 @@ class BaseManager:
14
15
  self.eio_to_sid = {}
15
16
  self.callbacks = {}
16
17
  self.pending_disconnect = {}
18
+ self.json = json
17
19
 
18
20
  def set_server(self, server):
19
21
  self.server = server
22
+ self.json = self.server.packet_class.json # use the global JSON module
20
23
 
21
24
  def initialize(self):
22
25
  """Invoked before the first request is received. Subclasses can add
@@ -39,10 +39,11 @@ class Client(base_client.BaseClient):
39
39
  of the ``encode()`` and ``decode()`` methods can be
40
40
  provided. Client and server must use compatible
41
41
  serializers.
42
- :param json: An alternative json module to use for encoding and decoding
42
+ :param json: An alternative JSON module to use for encoding and decoding
43
43
  packets. Custom json modules must have ``dumps`` and ``loads``
44
44
  functions that are compatible with the standard library
45
- versions.
45
+ versions. This is a process-wide setting, all instantiated
46
+ servers and clients must use the same JSON module.
46
47
  :param handle_sigint: Set to ``True`` to automatically handle disconnection
47
48
  when the process is interrupted, or to ``False`` to
48
49
  leave interrupt handling to the calling application.
@@ -5,7 +5,6 @@ try:
5
5
  except ImportError:
6
6
  kafka = None
7
7
 
8
- from engineio import json
9
8
  from .pubsub_manager import PubSubManager
10
9
 
11
10
  logger = logging.getLogger('socketio')
@@ -32,18 +31,29 @@ class KafkaManager(PubSubManager): # pragma: no cover
32
31
  servers.
33
32
  :param write_only: If set to ``True``, only initialize to emit events. The
34
33
  default of ``False`` initializes the class for emitting
35
- and receiving.
34
+ and receiving. A write-only instance can be used
35
+ independently of the server to emit to clients from an
36
+ external process.
37
+ :param logger: a custom logger to log it. If not given, the server logger
38
+ is used.
39
+ :param json: An alternative JSON module to use for encoding and decoding
40
+ packets. Custom json modules must have ``dumps`` and ``loads``
41
+ functions that are compatible with the standard library
42
+ versions. This setting is only used when ``write_only`` is set
43
+ to ``True``. Otherwise the JSON module configured in the
44
+ server is used.
36
45
  """
37
46
  name = 'kafka'
38
47
 
39
48
  def __init__(self, url='kafka://localhost:9092', channel='socketio',
40
- write_only=False):
49
+ write_only=False, logger=None, json=None):
41
50
  if kafka is None:
42
51
  raise RuntimeError('kafka-python package is not installed '
43
52
  '(Run "pip install kafka-python" in your '
44
53
  'virtualenv).')
45
54
 
46
- super().__init__(channel=channel, write_only=write_only)
55
+ super().__init__(channel=channel, write_only=write_only, logger=logger,
56
+ json=json)
47
57
 
48
58
  urls = [url] if isinstance(url, str) else url
49
59
  self.kafka_urls = [url[8:] if url != 'kafka://' else 'localhost:9092'
@@ -53,7 +63,7 @@ class KafkaManager(PubSubManager): # pragma: no cover
53
63
  bootstrap_servers=self.kafka_urls)
54
64
 
55
65
  def _publish(self, data):
56
- self.producer.send(self.channel, value=json.dumps(data))
66
+ self.producer.send(self.channel, value=self.json.dumps(data))
57
67
  self.producer.flush()
58
68
 
59
69
  def _kafka_listen(self):