python-socketio 5.14.1__tar.gz → 5.14.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.
- {python_socketio-5.14.1/src/python_socketio.egg-info → python_socketio-5.14.2}/PKG-INFO +3 -1
- {python_socketio-5.14.1 → python_socketio-5.14.2}/pyproject.toml +4 -1
- {python_socketio-5.14.1 → python_socketio-5.14.2/src/python_socketio.egg-info}/PKG-INFO +3 -1
- {python_socketio-5.14.1 → python_socketio-5.14.2}/src/python_socketio.egg-info/requires.txt +3 -0
- {python_socketio-5.14.1 → python_socketio-5.14.2}/src/socketio/async_client.py +2 -2
- {python_socketio-5.14.1 → python_socketio-5.14.2}/src/socketio/async_pubsub_manager.py +12 -2
- {python_socketio-5.14.1 → python_socketio-5.14.2}/src/socketio/base_manager.py +7 -1
- {python_socketio-5.14.1 → python_socketio-5.14.2}/src/socketio/client.py +1 -1
- {python_socketio-5.14.1 → python_socketio-5.14.2}/src/socketio/packet.py +22 -18
- {python_socketio-5.14.1 → python_socketio-5.14.2}/src/socketio/pubsub_manager.py +12 -2
- {python_socketio-5.14.1 → python_socketio-5.14.2}/tests/async/test_client.py +54 -0
- {python_socketio-5.14.1 → python_socketio-5.14.2}/tests/async/test_pubsub_manager.py +67 -0
- {python_socketio-5.14.1 → python_socketio-5.14.2}/tests/common/test_client.py +56 -0
- {python_socketio-5.14.1 → python_socketio-5.14.2}/tests/common/test_packet.py +16 -8
- {python_socketio-5.14.1 → python_socketio-5.14.2}/tests/common/test_pubsub_manager.py +65 -0
- {python_socketio-5.14.1 → python_socketio-5.14.2}/tox.ini +2 -1
- {python_socketio-5.14.1 → python_socketio-5.14.2}/LICENSE +0 -0
- {python_socketio-5.14.1 → python_socketio-5.14.2}/MANIFEST.in +0 -0
- {python_socketio-5.14.1 → python_socketio-5.14.2}/README.md +0 -0
- {python_socketio-5.14.1 → python_socketio-5.14.2}/docs/Makefile +0 -0
- {python_socketio-5.14.1 → python_socketio-5.14.2}/docs/_static/README.md +0 -0
- {python_socketio-5.14.1 → python_socketio-5.14.2}/docs/_static/custom.css +0 -0
- {python_socketio-5.14.1 → python_socketio-5.14.2}/docs/api.rst +0 -0
- {python_socketio-5.14.1 → python_socketio-5.14.2}/docs/client.rst +0 -0
- {python_socketio-5.14.1 → python_socketio-5.14.2}/docs/conf.py +0 -0
- {python_socketio-5.14.1 → python_socketio-5.14.2}/docs/index.rst +0 -0
- {python_socketio-5.14.1 → python_socketio-5.14.2}/docs/intro.rst +0 -0
- {python_socketio-5.14.1 → python_socketio-5.14.2}/docs/make.bat +0 -0
- {python_socketio-5.14.1 → python_socketio-5.14.2}/docs/server.rst +0 -0
- {python_socketio-5.14.1 → python_socketio-5.14.2}/setup.cfg +0 -0
- {python_socketio-5.14.1 → python_socketio-5.14.2}/src/python_socketio.egg-info/SOURCES.txt +0 -0
- {python_socketio-5.14.1 → python_socketio-5.14.2}/src/python_socketio.egg-info/dependency_links.txt +0 -0
- {python_socketio-5.14.1 → python_socketio-5.14.2}/src/python_socketio.egg-info/not-zip-safe +0 -0
- {python_socketio-5.14.1 → python_socketio-5.14.2}/src/python_socketio.egg-info/top_level.txt +0 -0
- {python_socketio-5.14.1 → python_socketio-5.14.2}/src/socketio/__init__.py +0 -0
- {python_socketio-5.14.1 → python_socketio-5.14.2}/src/socketio/admin.py +0 -0
- {python_socketio-5.14.1 → python_socketio-5.14.2}/src/socketio/asgi.py +0 -0
- {python_socketio-5.14.1 → python_socketio-5.14.2}/src/socketio/async_admin.py +0 -0
- {python_socketio-5.14.1 → python_socketio-5.14.2}/src/socketio/async_aiopika_manager.py +0 -0
- {python_socketio-5.14.1 → python_socketio-5.14.2}/src/socketio/async_manager.py +0 -0
- {python_socketio-5.14.1 → python_socketio-5.14.2}/src/socketio/async_namespace.py +0 -0
- {python_socketio-5.14.1 → python_socketio-5.14.2}/src/socketio/async_redis_manager.py +0 -0
- {python_socketio-5.14.1 → python_socketio-5.14.2}/src/socketio/async_server.py +0 -0
- {python_socketio-5.14.1 → python_socketio-5.14.2}/src/socketio/async_simple_client.py +0 -0
- {python_socketio-5.14.1 → python_socketio-5.14.2}/src/socketio/base_client.py +0 -0
- {python_socketio-5.14.1 → python_socketio-5.14.2}/src/socketio/base_namespace.py +0 -0
- {python_socketio-5.14.1 → python_socketio-5.14.2}/src/socketio/base_server.py +0 -0
- {python_socketio-5.14.1 → python_socketio-5.14.2}/src/socketio/exceptions.py +0 -0
- {python_socketio-5.14.1 → python_socketio-5.14.2}/src/socketio/kafka_manager.py +0 -0
- {python_socketio-5.14.1 → python_socketio-5.14.2}/src/socketio/kombu_manager.py +0 -0
- {python_socketio-5.14.1 → python_socketio-5.14.2}/src/socketio/manager.py +0 -0
- {python_socketio-5.14.1 → python_socketio-5.14.2}/src/socketio/middleware.py +0 -0
- {python_socketio-5.14.1 → python_socketio-5.14.2}/src/socketio/msgpack_packet.py +0 -0
- {python_socketio-5.14.1 → python_socketio-5.14.2}/src/socketio/namespace.py +0 -0
- {python_socketio-5.14.1 → python_socketio-5.14.2}/src/socketio/redis_manager.py +0 -0
- {python_socketio-5.14.1 → python_socketio-5.14.2}/src/socketio/server.py +0 -0
- {python_socketio-5.14.1 → python_socketio-5.14.2}/src/socketio/simple_client.py +0 -0
- {python_socketio-5.14.1 → python_socketio-5.14.2}/src/socketio/tornado.py +0 -0
- {python_socketio-5.14.1 → python_socketio-5.14.2}/src/socketio/zmq_manager.py +0 -0
- {python_socketio-5.14.1 → python_socketio-5.14.2}/tests/__init__.py +0 -0
- {python_socketio-5.14.1 → python_socketio-5.14.2}/tests/async/__init__.py +0 -0
- {python_socketio-5.14.1 → python_socketio-5.14.2}/tests/async/test_admin.py +0 -0
- {python_socketio-5.14.1 → python_socketio-5.14.2}/tests/async/test_manager.py +0 -0
- {python_socketio-5.14.1 → python_socketio-5.14.2}/tests/async/test_namespace.py +0 -0
- {python_socketio-5.14.1 → python_socketio-5.14.2}/tests/async/test_redis_manager.py +0 -0
- {python_socketio-5.14.1 → python_socketio-5.14.2}/tests/async/test_server.py +0 -0
- {python_socketio-5.14.1 → python_socketio-5.14.2}/tests/async/test_simple_client.py +0 -0
- {python_socketio-5.14.1 → python_socketio-5.14.2}/tests/asyncio_web_server.py +0 -0
- {python_socketio-5.14.1 → python_socketio-5.14.2}/tests/common/__init__.py +0 -0
- {python_socketio-5.14.1 → python_socketio-5.14.2}/tests/common/test_admin.py +0 -0
- {python_socketio-5.14.1 → python_socketio-5.14.2}/tests/common/test_manager.py +0 -0
- {python_socketio-5.14.1 → python_socketio-5.14.2}/tests/common/test_middleware.py +0 -0
- {python_socketio-5.14.1 → python_socketio-5.14.2}/tests/common/test_msgpack_packet.py +0 -0
- {python_socketio-5.14.1 → python_socketio-5.14.2}/tests/common/test_namespace.py +0 -0
- {python_socketio-5.14.1 → python_socketio-5.14.2}/tests/common/test_redis_manager.py +0 -0
- {python_socketio-5.14.1 → python_socketio-5.14.2}/tests/common/test_server.py +0 -0
- {python_socketio-5.14.1 → python_socketio-5.14.2}/tests/common/test_simple_client.py +0 -0
- {python_socketio-5.14.1 → python_socketio-5.14.2}/tests/performance/README.md +0 -0
- {python_socketio-5.14.1 → python_socketio-5.14.2}/tests/performance/binary_packet.py +0 -0
- {python_socketio-5.14.1 → python_socketio-5.14.2}/tests/performance/json_packet.py +0 -0
- {python_socketio-5.14.1 → python_socketio-5.14.2}/tests/performance/namespace_packet.py +0 -0
- {python_socketio-5.14.1 → python_socketio-5.14.2}/tests/performance/run.sh +0 -0
- {python_socketio-5.14.1 → python_socketio-5.14.2}/tests/performance/server_receive.py +0 -0
- {python_socketio-5.14.1 → python_socketio-5.14.2}/tests/performance/server_send.py +0 -0
- {python_socketio-5.14.1 → python_socketio-5.14.2}/tests/performance/server_send_broadcast.py +0 -0
- {python_socketio-5.14.1 → python_socketio-5.14.2}/tests/performance/text_packet.py +0 -0
- {python_socketio-5.14.1 → python_socketio-5.14.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.14.
|
|
3
|
+
Version: 5.14.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
|
|
@@ -20,6 +20,8 @@ Requires-Dist: requests>=2.21.0; extra == "client"
|
|
|
20
20
|
Requires-Dist: websocket-client>=0.54.0; extra == "client"
|
|
21
21
|
Provides-Extra: asyncio-client
|
|
22
22
|
Requires-Dist: aiohttp>=3.4; extra == "asyncio-client"
|
|
23
|
+
Provides-Extra: dev
|
|
24
|
+
Requires-Dist: tox; extra == "dev"
|
|
23
25
|
Provides-Extra: docs
|
|
24
26
|
Requires-Dist: sphinx; extra == "docs"
|
|
25
27
|
Dynamic: license-file
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "python-socketio"
|
|
3
|
-
version = "5.14.
|
|
3
|
+
version = "5.14.2"
|
|
4
4
|
license = {text = "MIT"}
|
|
5
5
|
authors = [
|
|
6
6
|
{ name = "Miguel Grinberg", email = "miguel.grinberg@gmail.com" },
|
|
@@ -34,6 +34,9 @@ client = [
|
|
|
34
34
|
asyncio_client = [
|
|
35
35
|
"aiohttp >= 3.4",
|
|
36
36
|
]
|
|
37
|
+
dev = [
|
|
38
|
+
"tox",
|
|
39
|
+
]
|
|
37
40
|
docs = [
|
|
38
41
|
"sphinx",
|
|
39
42
|
]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: python-socketio
|
|
3
|
-
Version: 5.14.
|
|
3
|
+
Version: 5.14.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
|
|
@@ -20,6 +20,8 @@ Requires-Dist: requests>=2.21.0; extra == "client"
|
|
|
20
20
|
Requires-Dist: websocket-client>=0.54.0; extra == "client"
|
|
21
21
|
Provides-Extra: asyncio-client
|
|
22
22
|
Requires-Dist: aiohttp>=3.4; extra == "asyncio-client"
|
|
23
|
+
Provides-Extra: dev
|
|
24
|
+
Requires-Dist: tox; extra == "dev"
|
|
23
25
|
Provides-Extra: docs
|
|
24
26
|
Requires-Dist: sphinx; extra == "docs"
|
|
25
27
|
Dynamic: license-file
|
|
@@ -175,8 +175,8 @@ class AsyncClient(base_client.BaseClient):
|
|
|
175
175
|
if set(self.namespaces) != set(self.connection_namespaces):
|
|
176
176
|
await self.disconnect()
|
|
177
177
|
raise exceptions.ConnectionError(
|
|
178
|
-
'One or more namespaces failed to connect'
|
|
179
|
-
', '.join(self.failed_namespaces))
|
|
178
|
+
'One or more namespaces failed to connect: '
|
|
179
|
+
+ ', '.join(self.failed_namespaces))
|
|
180
180
|
|
|
181
181
|
self.connected = True
|
|
182
182
|
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import asyncio
|
|
2
|
+
import base64
|
|
2
3
|
from functools import partial
|
|
3
4
|
import uuid
|
|
4
5
|
|
|
5
6
|
from engineio import json
|
|
6
7
|
|
|
7
8
|
from .async_manager import AsyncManager
|
|
9
|
+
from .packet import Packet
|
|
8
10
|
|
|
9
11
|
|
|
10
12
|
class AsyncPubSubManager(AsyncManager):
|
|
@@ -64,8 +66,12 @@ class AsyncPubSubManager(AsyncManager):
|
|
|
64
66
|
callback = (room, namespace, id)
|
|
65
67
|
else:
|
|
66
68
|
callback = None
|
|
69
|
+
binary = Packet.data_is_binary(data)
|
|
70
|
+
if binary:
|
|
71
|
+
data, attachments = Packet.deconstruct_binary(data)
|
|
72
|
+
data = [data, *[base64.b64encode(a).decode() for a in attachments]]
|
|
67
73
|
message = {'method': 'emit', 'event': event, 'data': data,
|
|
68
|
-
'namespace': namespace, 'room': room,
|
|
74
|
+
'binary': binary, 'namespace': namespace, 'room': room,
|
|
69
75
|
'skip_sid': skip_sid, 'callback': callback,
|
|
70
76
|
'host_id': self.host_id}
|
|
71
77
|
await self._handle_emit(message) # handle in this host
|
|
@@ -145,7 +151,11 @@ class AsyncPubSubManager(AsyncManager):
|
|
|
145
151
|
*remote_callback)
|
|
146
152
|
else:
|
|
147
153
|
callback = None
|
|
148
|
-
|
|
154
|
+
data = message['data']
|
|
155
|
+
if message.get('binary'):
|
|
156
|
+
attachments = [base64.b64decode(a) for a in data[1:]]
|
|
157
|
+
data = Packet.reconstruct_binary(data[0], attachments)
|
|
158
|
+
await super().emit(message['event'], data,
|
|
149
159
|
namespace=message.get('namespace'),
|
|
150
160
|
room=message.get('room'),
|
|
151
161
|
skip_sid=message.get('skip_sid'),
|
|
@@ -29,7 +29,13 @@ class BaseManager:
|
|
|
29
29
|
return self.rooms.keys()
|
|
30
30
|
|
|
31
31
|
def get_participants(self, namespace, room):
|
|
32
|
-
"""Return an iterable with the active participants in a room.
|
|
32
|
+
"""Return an iterable with the active participants in a room.
|
|
33
|
+
|
|
34
|
+
Note that in a multi-server scenario this method only returns the
|
|
35
|
+
participants connect to the server in which the method is called. There
|
|
36
|
+
is currently no functionality to assemble a complete list of users
|
|
37
|
+
across multiple servers.
|
|
38
|
+
"""
|
|
33
39
|
ns = self.rooms.get(namespace, {})
|
|
34
40
|
if hasattr(room, '__len__') and not isinstance(room, str):
|
|
35
41
|
participants = ns[room[0]]._fwdm.copy() if room[0] in ns else {}
|
|
@@ -169,7 +169,7 @@ class Client(base_client.BaseClient):
|
|
|
169
169
|
self.disconnect()
|
|
170
170
|
raise exceptions.ConnectionError(
|
|
171
171
|
'One or more namespaces failed to connect: '
|
|
172
|
-
', '.join(self.failed_namespaces))
|
|
172
|
+
+ ', '.join(self.failed_namespaces))
|
|
173
173
|
|
|
174
174
|
self.connected = True
|
|
175
175
|
|
|
@@ -29,7 +29,7 @@ class Packet:
|
|
|
29
29
|
self.namespace = namespace
|
|
30
30
|
self.id = id
|
|
31
31
|
if self.uses_binary_events and \
|
|
32
|
-
(binary or (binary is None and self.
|
|
32
|
+
(binary or (binary is None and self.data_is_binary(
|
|
33
33
|
self.data))):
|
|
34
34
|
if self.packet_type == EVENT:
|
|
35
35
|
self.packet_type = BINARY_EVENT
|
|
@@ -51,7 +51,7 @@ class Packet:
|
|
|
51
51
|
"""
|
|
52
52
|
encoded_packet = str(self.packet_type)
|
|
53
53
|
if self.packet_type == BINARY_EVENT or self.packet_type == BINARY_ACK:
|
|
54
|
-
data, attachments = self.
|
|
54
|
+
data, attachments = self.deconstruct_binary(self.data)
|
|
55
55
|
encoded_packet += str(len(attachments)) + '-'
|
|
56
56
|
else:
|
|
57
57
|
data = self.data
|
|
@@ -119,61 +119,65 @@ class Packet:
|
|
|
119
119
|
raise ValueError('Unexpected binary attachment')
|
|
120
120
|
self.attachments.append(attachment)
|
|
121
121
|
if self.attachment_count == len(self.attachments):
|
|
122
|
-
self.reconstruct_binary(self.attachments)
|
|
122
|
+
self.data = self.reconstruct_binary(self.data, self.attachments)
|
|
123
123
|
return True
|
|
124
124
|
return False
|
|
125
125
|
|
|
126
|
-
|
|
126
|
+
@classmethod
|
|
127
|
+
def reconstruct_binary(cls, data, attachments):
|
|
127
128
|
"""Reconstruct a decoded packet using the given list of binary
|
|
128
129
|
attachments.
|
|
129
130
|
"""
|
|
130
|
-
|
|
131
|
-
self.attachments)
|
|
131
|
+
return cls._reconstruct_binary_internal(data, attachments)
|
|
132
132
|
|
|
133
|
-
|
|
133
|
+
@classmethod
|
|
134
|
+
def _reconstruct_binary_internal(cls, data, attachments):
|
|
134
135
|
if isinstance(data, list):
|
|
135
|
-
return [
|
|
136
|
+
return [cls._reconstruct_binary_internal(item, attachments)
|
|
136
137
|
for item in data]
|
|
137
138
|
elif isinstance(data, dict):
|
|
138
139
|
if data.get('_placeholder') and 'num' in data:
|
|
139
140
|
return attachments[data['num']]
|
|
140
141
|
else:
|
|
141
|
-
return {key:
|
|
142
|
-
|
|
142
|
+
return {key: cls._reconstruct_binary_internal(value,
|
|
143
|
+
attachments)
|
|
143
144
|
for key, value in data.items()}
|
|
144
145
|
else:
|
|
145
146
|
return data
|
|
146
147
|
|
|
147
|
-
|
|
148
|
+
@classmethod
|
|
149
|
+
def deconstruct_binary(cls, data):
|
|
148
150
|
"""Extract binary components in the packet."""
|
|
149
151
|
attachments = []
|
|
150
|
-
data =
|
|
152
|
+
data = cls._deconstruct_binary_internal(data, attachments)
|
|
151
153
|
return data, attachments
|
|
152
154
|
|
|
153
|
-
|
|
155
|
+
@classmethod
|
|
156
|
+
def _deconstruct_binary_internal(cls, data, attachments):
|
|
154
157
|
if isinstance(data, bytes):
|
|
155
158
|
attachments.append(data)
|
|
156
159
|
return {'_placeholder': True, 'num': len(attachments) - 1}
|
|
157
160
|
elif isinstance(data, list):
|
|
158
|
-
return [
|
|
161
|
+
return [cls._deconstruct_binary_internal(item, attachments)
|
|
159
162
|
for item in data]
|
|
160
163
|
elif isinstance(data, dict):
|
|
161
|
-
return {key:
|
|
164
|
+
return {key: cls._deconstruct_binary_internal(value, attachments)
|
|
162
165
|
for key, value in data.items()}
|
|
163
166
|
else:
|
|
164
167
|
return data
|
|
165
168
|
|
|
166
|
-
|
|
169
|
+
@classmethod
|
|
170
|
+
def data_is_binary(cls, data):
|
|
167
171
|
"""Check if the data contains binary components."""
|
|
168
172
|
if isinstance(data, bytes):
|
|
169
173
|
return True
|
|
170
174
|
elif isinstance(data, list):
|
|
171
175
|
return functools.reduce(
|
|
172
|
-
lambda a, b: a or b, [
|
|
176
|
+
lambda a, b: a or b, [cls.data_is_binary(item)
|
|
173
177
|
for item in data], False)
|
|
174
178
|
elif isinstance(data, dict):
|
|
175
179
|
return functools.reduce(
|
|
176
|
-
lambda a, b: a or b, [
|
|
180
|
+
lambda a, b: a or b, [cls.data_is_binary(item)
|
|
177
181
|
for item in data.values()],
|
|
178
182
|
False)
|
|
179
183
|
else:
|
|
@@ -1,9 +1,11 @@
|
|
|
1
|
+
import base64
|
|
1
2
|
from functools import partial
|
|
2
3
|
import uuid
|
|
3
4
|
|
|
4
5
|
from engineio import json
|
|
5
6
|
|
|
6
7
|
from .manager import Manager
|
|
8
|
+
from .packet import Packet
|
|
7
9
|
|
|
8
10
|
|
|
9
11
|
class PubSubManager(Manager):
|
|
@@ -61,8 +63,12 @@ class PubSubManager(Manager):
|
|
|
61
63
|
callback = (room, namespace, id)
|
|
62
64
|
else:
|
|
63
65
|
callback = None
|
|
66
|
+
binary = Packet.data_is_binary(data)
|
|
67
|
+
if binary:
|
|
68
|
+
data, attachments = Packet.deconstruct_binary(data)
|
|
69
|
+
data = [data, *[base64.b64encode(a).decode() for a in attachments]]
|
|
64
70
|
message = {'method': 'emit', 'event': event, 'data': data,
|
|
65
|
-
'namespace': namespace, 'room': room,
|
|
71
|
+
'binary': binary, 'namespace': namespace, 'room': room,
|
|
66
72
|
'skip_sid': skip_sid, 'callback': callback,
|
|
67
73
|
'host_id': self.host_id}
|
|
68
74
|
self._handle_emit(message) # handle in this host
|
|
@@ -141,7 +147,11 @@ class PubSubManager(Manager):
|
|
|
141
147
|
*remote_callback)
|
|
142
148
|
else:
|
|
143
149
|
callback = None
|
|
144
|
-
|
|
150
|
+
data = message['data']
|
|
151
|
+
if message.get('binary'):
|
|
152
|
+
attachments = [base64.b64decode(a) for a in data[1:]]
|
|
153
|
+
data = Packet.reconstruct_binary(data[0], attachments)
|
|
154
|
+
super().emit(message['event'], data,
|
|
145
155
|
namespace=message.get('namespace'),
|
|
146
156
|
room=message.get('room'),
|
|
147
157
|
skip_sid=message.get('skip_sid'), callback=callback)
|
|
@@ -203,6 +203,60 @@ class TestAsyncClient:
|
|
|
203
203
|
assert c.connected is True
|
|
204
204
|
assert c.namespaces == {'/bar': '123', '/foo': '456'}
|
|
205
205
|
|
|
206
|
+
async def test_connect_wait_one_namespaces_error(self):
|
|
207
|
+
c = async_client.AsyncClient()
|
|
208
|
+
c.eio.connect = mock.AsyncMock()
|
|
209
|
+
c._connect_event = mock.MagicMock()
|
|
210
|
+
|
|
211
|
+
async def mock_connect():
|
|
212
|
+
if c.failed_namespaces == []:
|
|
213
|
+
c.failed_namespaces = ['/foo']
|
|
214
|
+
return True
|
|
215
|
+
return False
|
|
216
|
+
|
|
217
|
+
c._connect_event.wait = mock_connect
|
|
218
|
+
with pytest.raises(exceptions.ConnectionError,
|
|
219
|
+
match='failed to connect: /foo'):
|
|
220
|
+
await c.connect(
|
|
221
|
+
'url',
|
|
222
|
+
namespaces=['/foo'],
|
|
223
|
+
wait=True,
|
|
224
|
+
wait_timeout=0.01,
|
|
225
|
+
)
|
|
226
|
+
assert c.connected is False
|
|
227
|
+
assert c.namespaces == {}
|
|
228
|
+
assert c.failed_namespaces == ['/foo']
|
|
229
|
+
|
|
230
|
+
async def test_connect_wait_three_namespaces_error(self):
|
|
231
|
+
c = async_client.AsyncClient()
|
|
232
|
+
c.eio.connect = mock.AsyncMock()
|
|
233
|
+
c._connect_event = mock.MagicMock()
|
|
234
|
+
|
|
235
|
+
async def mock_connect():
|
|
236
|
+
if c.namespaces == {}:
|
|
237
|
+
c.namespaces = {'/bar': '123'}
|
|
238
|
+
return True
|
|
239
|
+
elif c.namespaces == {'/bar': '123'} and c.failed_namespaces == []:
|
|
240
|
+
c.failed_namespaces = ['/baz']
|
|
241
|
+
return True
|
|
242
|
+
elif c.failed_namespaces == ['/baz']:
|
|
243
|
+
c.failed_namespaces = ['/baz', '/foo']
|
|
244
|
+
return True
|
|
245
|
+
return False
|
|
246
|
+
|
|
247
|
+
c._connect_event.wait = mock_connect
|
|
248
|
+
with pytest.raises(exceptions.ConnectionError,
|
|
249
|
+
match='failed to connect: /baz, /foo'):
|
|
250
|
+
await c.connect(
|
|
251
|
+
'url',
|
|
252
|
+
namespaces=['/foo', '/bar', '/baz'],
|
|
253
|
+
wait=True,
|
|
254
|
+
wait_timeout=0.01,
|
|
255
|
+
)
|
|
256
|
+
assert c.connected is False
|
|
257
|
+
assert c.namespaces == {'/bar': '123'}
|
|
258
|
+
assert c.failed_namespaces == ['/baz', '/foo']
|
|
259
|
+
|
|
206
260
|
async def test_connect_timeout(self):
|
|
207
261
|
c = async_client.AsyncClient()
|
|
208
262
|
c.eio.connect = mock.AsyncMock()
|
|
@@ -57,6 +57,7 @@ class TestAsyncPubSubManager:
|
|
|
57
57
|
{
|
|
58
58
|
'method': 'emit',
|
|
59
59
|
'event': 'foo',
|
|
60
|
+
'binary': False,
|
|
60
61
|
'data': 'bar',
|
|
61
62
|
'namespace': '/',
|
|
62
63
|
'room': None,
|
|
@@ -66,6 +67,36 @@ class TestAsyncPubSubManager:
|
|
|
66
67
|
}
|
|
67
68
|
)
|
|
68
69
|
|
|
70
|
+
async def test_emit_binary(self):
|
|
71
|
+
await self.pm.emit('foo', b'bar')
|
|
72
|
+
self.pm._publish.assert_awaited_once_with(
|
|
73
|
+
{
|
|
74
|
+
'method': 'emit',
|
|
75
|
+
'event': 'foo',
|
|
76
|
+
'binary': True,
|
|
77
|
+
'data': [{'_placeholder': True, 'num': 0}, 'YmFy'],
|
|
78
|
+
'namespace': '/',
|
|
79
|
+
'room': None,
|
|
80
|
+
'skip_sid': None,
|
|
81
|
+
'callback': None,
|
|
82
|
+
'host_id': '123456',
|
|
83
|
+
}
|
|
84
|
+
)
|
|
85
|
+
await self.pm.emit('foo', {'foo': b'bar'})
|
|
86
|
+
self.pm._publish.assert_awaited_with(
|
|
87
|
+
{
|
|
88
|
+
'method': 'emit',
|
|
89
|
+
'event': 'foo',
|
|
90
|
+
'binary': True,
|
|
91
|
+
'data': [{'foo': {'_placeholder': True, 'num': 0}}, 'YmFy'],
|
|
92
|
+
'namespace': '/',
|
|
93
|
+
'room': None,
|
|
94
|
+
'skip_sid': None,
|
|
95
|
+
'callback': None,
|
|
96
|
+
'host_id': '123456',
|
|
97
|
+
}
|
|
98
|
+
)
|
|
99
|
+
|
|
69
100
|
async def test_emit_with_to(self):
|
|
70
101
|
sid = 'room-mate'
|
|
71
102
|
await self.pm.emit('foo', 'bar', to=sid)
|
|
@@ -73,6 +104,7 @@ class TestAsyncPubSubManager:
|
|
|
73
104
|
{
|
|
74
105
|
'method': 'emit',
|
|
75
106
|
'event': 'foo',
|
|
107
|
+
'binary': False,
|
|
76
108
|
'data': 'bar',
|
|
77
109
|
'namespace': '/',
|
|
78
110
|
'room': sid,
|
|
@@ -88,6 +120,7 @@ class TestAsyncPubSubManager:
|
|
|
88
120
|
{
|
|
89
121
|
'method': 'emit',
|
|
90
122
|
'event': 'foo',
|
|
123
|
+
'binary': False,
|
|
91
124
|
'data': 'bar',
|
|
92
125
|
'namespace': '/baz',
|
|
93
126
|
'room': None,
|
|
@@ -103,6 +136,7 @@ class TestAsyncPubSubManager:
|
|
|
103
136
|
{
|
|
104
137
|
'method': 'emit',
|
|
105
138
|
'event': 'foo',
|
|
139
|
+
'binary': False,
|
|
106
140
|
'data': 'bar',
|
|
107
141
|
'namespace': '/',
|
|
108
142
|
'room': 'baz',
|
|
@@ -118,6 +152,7 @@ class TestAsyncPubSubManager:
|
|
|
118
152
|
{
|
|
119
153
|
'method': 'emit',
|
|
120
154
|
'event': 'foo',
|
|
155
|
+
'binary': False,
|
|
121
156
|
'data': 'bar',
|
|
122
157
|
'namespace': '/',
|
|
123
158
|
'room': None,
|
|
@@ -136,6 +171,7 @@ class TestAsyncPubSubManager:
|
|
|
136
171
|
{
|
|
137
172
|
'method': 'emit',
|
|
138
173
|
'event': 'foo',
|
|
174
|
+
'binary': False,
|
|
139
175
|
'data': 'bar',
|
|
140
176
|
'namespace': '/',
|
|
141
177
|
'room': 'baz',
|
|
@@ -241,6 +277,37 @@ class TestAsyncPubSubManager:
|
|
|
241
277
|
callback=None,
|
|
242
278
|
)
|
|
243
279
|
|
|
280
|
+
async def test_handle_emit_binary(self):
|
|
281
|
+
with mock.patch.object(
|
|
282
|
+
async_manager.AsyncManager, 'emit'
|
|
283
|
+
) as super_emit:
|
|
284
|
+
await self.pm._handle_emit({
|
|
285
|
+
'event': 'foo',
|
|
286
|
+
'binary': True,
|
|
287
|
+
'data': [{'_placeholder': True, 'num': 0}, 'YmFy'],
|
|
288
|
+
})
|
|
289
|
+
super_emit.assert_awaited_once_with(
|
|
290
|
+
'foo',
|
|
291
|
+
b'bar',
|
|
292
|
+
namespace=None,
|
|
293
|
+
room=None,
|
|
294
|
+
skip_sid=None,
|
|
295
|
+
callback=None,
|
|
296
|
+
)
|
|
297
|
+
await self.pm._handle_emit({
|
|
298
|
+
'event': 'foo',
|
|
299
|
+
'binary': True,
|
|
300
|
+
'data': [{'foo': {'_placeholder': True, 'num': 0}}, 'YmFy'],
|
|
301
|
+
})
|
|
302
|
+
super_emit.assert_awaited_with(
|
|
303
|
+
'foo',
|
|
304
|
+
{'foo': b'bar'},
|
|
305
|
+
namespace=None,
|
|
306
|
+
room=None,
|
|
307
|
+
skip_sid=None,
|
|
308
|
+
callback=None,
|
|
309
|
+
)
|
|
310
|
+
|
|
244
311
|
async def test_handle_emit_with_namespace(self):
|
|
245
312
|
with mock.patch.object(
|
|
246
313
|
async_manager.AsyncManager, 'emit'
|
|
@@ -350,6 +350,62 @@ class TestClient:
|
|
|
350
350
|
assert c.connected is True
|
|
351
351
|
assert c.namespaces == {'/bar': '123', '/foo': '456'}
|
|
352
352
|
|
|
353
|
+
def test_connect_wait_one_namespaces_error(self):
|
|
354
|
+
c = client.Client()
|
|
355
|
+
c.eio.connect = mock.MagicMock()
|
|
356
|
+
c._connect_event = mock.MagicMock()
|
|
357
|
+
|
|
358
|
+
def mock_connect(timeout):
|
|
359
|
+
assert timeout == 0.01
|
|
360
|
+
if c.failed_namespaces == []:
|
|
361
|
+
c.failed_namespaces = ['/foo']
|
|
362
|
+
return True
|
|
363
|
+
return False
|
|
364
|
+
|
|
365
|
+
c._connect_event.wait = mock_connect
|
|
366
|
+
with pytest.raises(exceptions.ConnectionError,
|
|
367
|
+
match='failed to connect: /foo'):
|
|
368
|
+
c.connect(
|
|
369
|
+
'url',
|
|
370
|
+
namespaces=['/foo'],
|
|
371
|
+
wait=True,
|
|
372
|
+
wait_timeout=0.01,
|
|
373
|
+
)
|
|
374
|
+
assert c.connected is False
|
|
375
|
+
assert c.namespaces == {}
|
|
376
|
+
assert c.failed_namespaces == ['/foo']
|
|
377
|
+
|
|
378
|
+
def test_connect_wait_three_namespaces_error(self):
|
|
379
|
+
c = client.Client()
|
|
380
|
+
c.eio.connect = mock.MagicMock()
|
|
381
|
+
c._connect_event = mock.MagicMock()
|
|
382
|
+
|
|
383
|
+
def mock_connect(timeout):
|
|
384
|
+
assert timeout == 0.01
|
|
385
|
+
if c.namespaces == {}:
|
|
386
|
+
c.namespaces = {'/bar': '123'}
|
|
387
|
+
return True
|
|
388
|
+
elif c.namespaces == {'/bar': '123'} and c.failed_namespaces == []:
|
|
389
|
+
c.failed_namespaces = ['/baz']
|
|
390
|
+
return True
|
|
391
|
+
elif c.failed_namespaces == ['/baz']:
|
|
392
|
+
c.failed_namespaces = ['/baz', '/foo']
|
|
393
|
+
return True
|
|
394
|
+
return False
|
|
395
|
+
|
|
396
|
+
c._connect_event.wait = mock_connect
|
|
397
|
+
with pytest.raises(exceptions.ConnectionError,
|
|
398
|
+
match='failed to connect: /baz, /foo'):
|
|
399
|
+
c.connect(
|
|
400
|
+
'url',
|
|
401
|
+
namespaces=['/foo', '/bar', '/baz'],
|
|
402
|
+
wait=True,
|
|
403
|
+
wait_timeout=0.01,
|
|
404
|
+
)
|
|
405
|
+
assert c.connected is False
|
|
406
|
+
assert c.namespaces == {'/bar': '123'}
|
|
407
|
+
assert c.failed_namespaces == ['/baz', '/foo']
|
|
408
|
+
|
|
353
409
|
def test_connect_timeout(self):
|
|
354
410
|
c = client.Client()
|
|
355
411
|
c.eio.connect = mock.MagicMock()
|
|
@@ -266,16 +266,24 @@ class TestPacket:
|
|
|
266
266
|
assert pkt.data["a"] == "0123456789-"
|
|
267
267
|
assert pkt.attachment_count == 0
|
|
268
268
|
|
|
269
|
+
def test_deconstruct_binary(self):
|
|
270
|
+
datas = [b'foo', [b'foo', b'bar'], ['foo', b'bar'], {'foo': b'bar'},
|
|
271
|
+
{'foo': 'bar', 'baz': b'qux'}, {'foo': [b'bar']}]
|
|
272
|
+
for data in datas:
|
|
273
|
+
bdata, attachments = packet.Packet.deconstruct_binary(data)
|
|
274
|
+
rdata = packet.Packet.reconstruct_binary(bdata, attachments)
|
|
275
|
+
assert data == rdata
|
|
276
|
+
|
|
269
277
|
def test_data_is_binary_list(self):
|
|
270
278
|
pkt = packet.Packet()
|
|
271
|
-
assert not pkt.
|
|
272
|
-
assert not pkt.
|
|
273
|
-
assert pkt.
|
|
274
|
-
assert pkt.
|
|
279
|
+
assert not pkt.data_is_binary(['foo'])
|
|
280
|
+
assert not pkt.data_is_binary([])
|
|
281
|
+
assert pkt.data_is_binary([b'foo'])
|
|
282
|
+
assert pkt.data_is_binary(['foo', b'bar'])
|
|
275
283
|
|
|
276
284
|
def test_data_is_binary_dict(self):
|
|
277
285
|
pkt = packet.Packet()
|
|
278
|
-
assert not pkt.
|
|
279
|
-
assert not pkt.
|
|
280
|
-
assert pkt.
|
|
281
|
-
assert pkt.
|
|
286
|
+
assert not pkt.data_is_binary({'a': 'foo'})
|
|
287
|
+
assert not pkt.data_is_binary({})
|
|
288
|
+
assert pkt.data_is_binary({'a': b'foo'})
|
|
289
|
+
assert pkt.data_is_binary({'a': 'foo', 'b': b'bar'})
|
|
@@ -69,6 +69,7 @@ class TestPubSubManager:
|
|
|
69
69
|
{
|
|
70
70
|
'method': 'emit',
|
|
71
71
|
'event': 'foo',
|
|
72
|
+
'binary': False,
|
|
72
73
|
'data': 'bar',
|
|
73
74
|
'namespace': '/',
|
|
74
75
|
'room': None,
|
|
@@ -78,6 +79,36 @@ class TestPubSubManager:
|
|
|
78
79
|
}
|
|
79
80
|
)
|
|
80
81
|
|
|
82
|
+
def test_emit_binary(self):
|
|
83
|
+
self.pm.emit('foo', b'bar')
|
|
84
|
+
self.pm._publish.assert_called_once_with(
|
|
85
|
+
{
|
|
86
|
+
'method': 'emit',
|
|
87
|
+
'event': 'foo',
|
|
88
|
+
'binary': True,
|
|
89
|
+
'data': [{'_placeholder': True, 'num': 0}, 'YmFy'],
|
|
90
|
+
'namespace': '/',
|
|
91
|
+
'room': None,
|
|
92
|
+
'skip_sid': None,
|
|
93
|
+
'callback': None,
|
|
94
|
+
'host_id': '123456',
|
|
95
|
+
}
|
|
96
|
+
)
|
|
97
|
+
self.pm.emit('foo', {'foo': b'bar'})
|
|
98
|
+
self.pm._publish.assert_called_with(
|
|
99
|
+
{
|
|
100
|
+
'method': 'emit',
|
|
101
|
+
'event': 'foo',
|
|
102
|
+
'binary': True,
|
|
103
|
+
'data': [{'foo': {'_placeholder': True, 'num': 0}}, 'YmFy'],
|
|
104
|
+
'namespace': '/',
|
|
105
|
+
'room': None,
|
|
106
|
+
'skip_sid': None,
|
|
107
|
+
'callback': None,
|
|
108
|
+
'host_id': '123456',
|
|
109
|
+
}
|
|
110
|
+
)
|
|
111
|
+
|
|
81
112
|
def test_emit_with_to(self):
|
|
82
113
|
sid = "ferris"
|
|
83
114
|
self.pm.emit('foo', 'bar', to=sid)
|
|
@@ -85,6 +116,7 @@ class TestPubSubManager:
|
|
|
85
116
|
{
|
|
86
117
|
'method': 'emit',
|
|
87
118
|
'event': 'foo',
|
|
119
|
+
'binary': False,
|
|
88
120
|
'data': 'bar',
|
|
89
121
|
'namespace': '/',
|
|
90
122
|
'room': sid,
|
|
@@ -100,6 +132,7 @@ class TestPubSubManager:
|
|
|
100
132
|
{
|
|
101
133
|
'method': 'emit',
|
|
102
134
|
'event': 'foo',
|
|
135
|
+
'binary': False,
|
|
103
136
|
'data': 'bar',
|
|
104
137
|
'namespace': '/baz',
|
|
105
138
|
'room': None,
|
|
@@ -115,6 +148,7 @@ class TestPubSubManager:
|
|
|
115
148
|
{
|
|
116
149
|
'method': 'emit',
|
|
117
150
|
'event': 'foo',
|
|
151
|
+
'binary': False,
|
|
118
152
|
'data': 'bar',
|
|
119
153
|
'namespace': '/',
|
|
120
154
|
'room': 'baz',
|
|
@@ -130,6 +164,7 @@ class TestPubSubManager:
|
|
|
130
164
|
{
|
|
131
165
|
'method': 'emit',
|
|
132
166
|
'event': 'foo',
|
|
167
|
+
'binary': False,
|
|
133
168
|
'data': 'bar',
|
|
134
169
|
'namespace': '/',
|
|
135
170
|
'room': None,
|
|
@@ -148,6 +183,7 @@ class TestPubSubManager:
|
|
|
148
183
|
{
|
|
149
184
|
'method': 'emit',
|
|
150
185
|
'event': 'foo',
|
|
186
|
+
'binary': False,
|
|
151
187
|
'data': 'bar',
|
|
152
188
|
'namespace': '/',
|
|
153
189
|
'room': 'baz',
|
|
@@ -250,6 +286,35 @@ class TestPubSubManager:
|
|
|
250
286
|
callback=None,
|
|
251
287
|
)
|
|
252
288
|
|
|
289
|
+
def test_handle_emit_binary(self):
|
|
290
|
+
with mock.patch.object(manager.Manager, 'emit') as super_emit:
|
|
291
|
+
self.pm._handle_emit({
|
|
292
|
+
'event': 'foo',
|
|
293
|
+
'binary': True,
|
|
294
|
+
'data': [{'_placeholder': True, 'num': 0}, 'YmFy'],
|
|
295
|
+
})
|
|
296
|
+
super_emit.assert_called_once_with(
|
|
297
|
+
'foo',
|
|
298
|
+
b'bar',
|
|
299
|
+
namespace=None,
|
|
300
|
+
room=None,
|
|
301
|
+
skip_sid=None,
|
|
302
|
+
callback=None,
|
|
303
|
+
)
|
|
304
|
+
self.pm._handle_emit({
|
|
305
|
+
'event': 'foo',
|
|
306
|
+
'binary': True,
|
|
307
|
+
'data': [{'foo': {'_placeholder': True, 'num': 0}}, 'YmFy'],
|
|
308
|
+
})
|
|
309
|
+
super_emit.assert_called_with(
|
|
310
|
+
'foo',
|
|
311
|
+
{'foo': b'bar'},
|
|
312
|
+
namespace=None,
|
|
313
|
+
room=None,
|
|
314
|
+
skip_sid=None,
|
|
315
|
+
callback=None,
|
|
316
|
+
)
|
|
317
|
+
|
|
253
318
|
def test_handle_emit_with_namespace(self):
|
|
254
319
|
with mock.patch.object(manager.Manager, 'emit') as super_emit:
|
|
255
320
|
self.pm._handle_emit(
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
[tox]
|
|
2
|
-
envlist=flake8,py{38,39,310,311,312,313},docs
|
|
2
|
+
envlist=flake8,py{38,39,310,311,312,313,314},docs
|
|
3
3
|
skip_missing_interpreters=True
|
|
4
4
|
|
|
5
5
|
[gh-actions]
|
|
@@ -10,6 +10,7 @@ python =
|
|
|
10
10
|
3.11: py311
|
|
11
11
|
3.12: py312
|
|
12
12
|
3.13: py313
|
|
13
|
+
3.14: py314
|
|
13
14
|
pypy-3: pypy3
|
|
14
15
|
|
|
15
16
|
[testenv]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_socketio-5.14.1 → python_socketio-5.14.2}/src/python_socketio.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
{python_socketio-5.14.1 → python_socketio-5.14.2}/src/python_socketio.egg-info/top_level.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_socketio-5.14.1 → python_socketio-5.14.2}/tests/performance/server_send_broadcast.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|