signalrcore 0.9.5__py3-none-any.whl → 0.9.6a2__py3-none-any.whl

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.

Potentially problematic release.


This version of signalrcore might be problematic. Click here for more details.

@@ -0,0 +1,263 @@
1
+ import socket
2
+ import ssl
3
+ import base64
4
+ import threading
5
+ import os
6
+ import struct
7
+ import urllib.parse as parse
8
+ from typing import Optional, Callable, Union
9
+ from signalrcore.helpers import Helpers
10
+
11
+
12
+ THREAD_NAME = "Signalrcore websocket client"
13
+ WINDOW_SIZE = 1024
14
+
15
+
16
+ class NoHeaderException(Exception):
17
+ """Error reading messages from socket, empty content
18
+ """
19
+ pass
20
+
21
+
22
+ class SocketHandshakeError(Exception):
23
+ """Error during connection
24
+
25
+ Args:
26
+ msg (str): message
27
+ """
28
+ def __init__(self, msg: str):
29
+ super().__init__(msg)
30
+
31
+
32
+ class WebSocketClient(object):
33
+ """Minimal websocket client
34
+
35
+ Args:
36
+ url (str): Websocket url
37
+ headers (Optional[dict]): additional headers
38
+ verify_ssl (bool): Verify SSL y/n
39
+ on_message (callable): on message callback
40
+ on_error (callable): on error callback
41
+ on_open (callable): on open callback
42
+ on_close (callable): on close callback
43
+ """
44
+ def __init__(
45
+ self,
46
+ url: str,
47
+ is_binary: bool = False,
48
+ headers: Optional[dict] = None,
49
+ proxies: dict = {},
50
+ verify_ssl: bool = True,
51
+ enable_trace: bool = False,
52
+ on_message: Callable = None,
53
+ on_open: Callable = None,
54
+ on_error: Callable = None,
55
+ on_close: Callable = None):
56
+ self.is_trace_enabled = enable_trace
57
+ self.proxies = proxies
58
+ self.url = url
59
+ self.is_binary = is_binary
60
+ self.headers = headers or {}
61
+ self.verify_ssl = verify_ssl
62
+ self.sock = None
63
+ self.ssl_context = ssl.create_default_context()\
64
+ if verify_ssl else\
65
+ ssl._create_unverified_context()
66
+ self.logger = Helpers.get_logger()
67
+ self.recv_thread = None
68
+ self.on_message = on_message
69
+ self.on_close = on_close
70
+ self.on_error = on_error
71
+ self.on_open = on_open
72
+ self.running = False
73
+ self.is_closing = False
74
+
75
+ def connect(self):
76
+ # ToDo URL PARSE
77
+ parsed_url = parse.urlparse(self.url)
78
+ is_secure_connection = parsed_url.scheme == "wss"\
79
+ or parsed_url.scheme == "https"
80
+
81
+ proxy_info = None
82
+ if is_secure_connection\
83
+ and self.proxies.get("https", None) is not None:
84
+ proxy_info = parse.urlparse(self.proxies.get("https"))
85
+
86
+ if not is_secure_connection\
87
+ and self.proxies.get("http", None) is not None:
88
+ proxy_info = parse.urlparse(self.proxies.get("http"))
89
+
90
+ host, port = parsed_url.hostname, parsed_url.port
91
+
92
+ if proxy_info is not None:
93
+ host = proxy_info.hostname,
94
+ port = proxy_info.port
95
+
96
+ raw_sock = socket.create_connection((host, port))
97
+
98
+ if is_secure_connection:
99
+ raw_sock = self.ssl_context.wrap_socket(
100
+ raw_sock,
101
+ server_hostname=host)
102
+
103
+ self.sock = raw_sock
104
+
105
+ # Perform the WebSocket handshake
106
+ key = base64.b64encode(os.urandom(16)).decode("utf-8")
107
+ request_headers = [
108
+ f"GET {parsed_url.path} HTTP/1.1",
109
+ f"Host: {parsed_url.hostname}",
110
+ "Upgrade: websocket",
111
+ "Connection: Upgrade",
112
+ f"Sec-WebSocket-Key: {key}",
113
+ "Sec-WebSocket-Version: 13"
114
+ ]
115
+ for k, v in self.headers.items():
116
+ request_headers.append(f"{k}: {v}")
117
+
118
+ request = "\r\n".join(request_headers) + "\r\n\r\n"
119
+ req = request.encode("utf-8")
120
+
121
+ if self.is_trace_enabled:
122
+ self.logger.debug(req)
123
+
124
+ self.sock.sendall(req)
125
+
126
+ # Read handshake response
127
+ response = b""
128
+ while b"\r\n\r\n" not in response:
129
+ chunk = self.sock.recv(WINDOW_SIZE)
130
+ if self.is_trace_enabled:
131
+ self.logger.debug(chunk)
132
+
133
+ if not chunk:
134
+ raise SocketHandshakeError(
135
+ "Connection closed during handshake")
136
+
137
+ response += chunk
138
+
139
+ if b"101" not in response:
140
+ raise SocketHandshakeError(
141
+ f"Handshake failed: {response.decode()}")
142
+
143
+ self.running = True
144
+ self.recv_thread = threading.Thread(
145
+ target=self._recv_loop,
146
+ name=THREAD_NAME)
147
+ self.recv_thread.daemon = True
148
+ self.recv_thread.start()
149
+
150
+ def _recv_loop(self):
151
+ self.on_open()
152
+ try:
153
+ while self.running:
154
+ message = self._recv_frame()
155
+
156
+ if self.on_message:
157
+ self.on_message(self, message)
158
+ except Exception as e:
159
+ self.running = False
160
+
161
+ # is closing and no header indicates
162
+ # that socket has not received anything
163
+ has_no_content = type(e) is NoHeaderException
164
+
165
+ # is closing and errno indicates
166
+ # that file descriptor points to a closed file
167
+ has_closed_fd = type(e) is OSError and e.errno == 9
168
+
169
+ if (has_no_content or has_closed_fd) and self.is_closing:
170
+ return
171
+
172
+ if self.logger:
173
+ self.logger.error(f"Receive error: {e}")
174
+ self.on_error(e)
175
+
176
+ def _recv_frame(self):
177
+ # Very basic, single-frame, unfragmented
178
+ try:
179
+ header = self.sock.recv(2)
180
+ except ssl.SSLError as ex:
181
+ self.logger.error(ex)
182
+ header = None
183
+
184
+ if header is None or len(header) < 2:
185
+ raise NoHeaderException()
186
+
187
+ fin_opcode = header[0]
188
+ masked_len = header[1]
189
+
190
+ if self.logger:
191
+ self.logger.debug(
192
+ f"fin opcode: {fin_opcode}, masked len: {masked_len}")
193
+
194
+ payload_len = masked_len & 0x7F
195
+ if payload_len == 126:
196
+ payload_len = struct.unpack(">H", self.sock.recv(2))[0]
197
+ elif payload_len == 127:
198
+ payload_len = struct.unpack(">Q", self.sock.recv(8))[0]
199
+
200
+ if masked_len & 0x80:
201
+ masking_key = self.sock.recv(4)
202
+ masked_data = self.sock.recv(payload_len)
203
+ data = bytes(
204
+ b ^ masking_key[i % 4]
205
+ for i, b in enumerate(masked_data))
206
+ else:
207
+ data = self.sock.recv(payload_len)
208
+
209
+ if self.is_trace_enabled:
210
+ self.logger.debug(data)
211
+
212
+ if self.is_binary:
213
+ return data
214
+
215
+ return data.decode("utf-8")
216
+
217
+ def send(
218
+ self,
219
+ message: Union[str, bytes],
220
+ opcode=0x1):
221
+ # Text or binary opcode (no fragmentation)
222
+ payload = message.encode("utf-8")\
223
+ if type(message) is str else message
224
+ header = bytes([0x80 | opcode])
225
+ length = len(payload)
226
+ if length <= 125:
227
+ header += bytes([0x80 | length])
228
+ elif length <= 65535:
229
+ header += bytes([0x80 | 126]) + struct.pack(">H", length)
230
+ else:
231
+ header += bytes([0x80 | 127]) + struct.pack(">Q", length)
232
+
233
+ # Mask the payload
234
+ masking_key = os.urandom(4)
235
+ masked_payload = bytes(
236
+ b ^ masking_key[i % 4]
237
+ for i, b in enumerate(payload))
238
+ frame = header + masking_key + masked_payload
239
+ self.sock.sendall(frame)
240
+
241
+ def dispose(self):
242
+ if self.sock:
243
+ self.sock.close()
244
+ is_same_thread = threading.current_thread().name == THREAD_NAME
245
+ if self.recv_thread and not is_same_thread:
246
+ self.recv_thread.join()
247
+ self.recv_thread = None
248
+
249
+ def close(self):
250
+ self.logger.debug("Start closing socket")
251
+ try:
252
+ self.is_closing = True
253
+ self.running = False
254
+
255
+ self.dispose()
256
+
257
+ self.on_close()
258
+ self.logger.debug("socket closed successfully")
259
+ except Exception as ex:
260
+ self.logger.error(ex)
261
+ self.on_error(ex)
262
+ finally:
263
+ self.is_closing = False
@@ -1,20 +1,18 @@
1
- import websocket
2
- import threading
3
- import requests
4
1
  import traceback
5
2
  import time
6
- import ssl
7
3
  from .reconnection import ConnectionStateChecker
8
4
  from .connection import ConnectionState
9
5
  from ...messages.ping_message import PingMessage
10
- from ...hub.errors import HubError, HubConnectionError, UnAuthorizedHubError
6
+ from ...hub.errors import HubError, UnAuthorizedHubError
11
7
  from ...protocol.messagepack_protocol import MessagePackHubProtocol
12
- from ...protocol.json_hub_protocol import JsonHubProtocol
13
8
  from ..base_transport import BaseTransport
14
- from ...helpers import Helpers
9
+ from ...helpers import Helpers, RequestHelpers
10
+ from .websocket_client import WebSocketClient
11
+
15
12
 
16
13
  class WebsocketTransport(BaseTransport):
17
- def __init__(self,
14
+ def __init__(
15
+ self,
18
16
  url="",
19
17
  headers=None,
20
18
  keep_alive_interval=15,
@@ -22,13 +20,14 @@ class WebsocketTransport(BaseTransport):
22
20
  verify_ssl=False,
23
21
  skip_negotiation=False,
24
22
  enable_trace=False,
23
+ proxies: dict = {},
25
24
  **kwargs):
26
25
  super(WebsocketTransport, self).__init__(**kwargs)
27
26
  self._ws = None
28
27
  self.enable_trace = enable_trace
29
- self._thread = None
30
28
  self.skip_negotiation = skip_negotiation
31
29
  self.url = url
30
+ self.proxies = proxies
32
31
  if headers is None:
33
32
  self.headers = dict()
34
33
  else:
@@ -37,7 +36,6 @@ class WebsocketTransport(BaseTransport):
37
36
  self.token = None # auth
38
37
  self.state = ConnectionState.disconnected
39
38
  self.connection_alive = False
40
- self._thread = None
41
39
  self._ws = None
42
40
  self.verify_ssl = verify_ssl
43
41
  self.connection_checker = ConnectionStateChecker(
@@ -46,9 +44,6 @@ class WebsocketTransport(BaseTransport):
46
44
  )
47
45
  self.reconnection_handler = reconnection_handler
48
46
 
49
- if len(self.logger.handlers) > 0:
50
- websocket.enableTrace(self.enable_trace, self.logger.handlers[0])
51
-
52
47
  def is_running(self):
53
48
  return self.state != ConnectionState.disconnected
54
49
 
@@ -56,8 +51,11 @@ class WebsocketTransport(BaseTransport):
56
51
  if self.state == ConnectionState.connected:
57
52
  self.connection_checker.stop()
58
53
  self._ws.close()
59
- self.state = ConnectionState.disconnected
60
- self.handshake_received = False
54
+ self.state = ConnectionState.disconnected
55
+ self.handshake_received = False
56
+
57
+ def is_trace_enabled(self) -> bool:
58
+ return self._ws.is_trace_enabled
61
59
 
62
60
  def start(self):
63
61
  if not self.skip_negotiation:
@@ -69,39 +67,41 @@ class WebsocketTransport(BaseTransport):
69
67
 
70
68
  self.state = ConnectionState.connecting
71
69
  self.logger.debug("start url:" + self.url)
72
-
73
- self._ws = websocket.WebSocketApp(
70
+
71
+ self._ws = WebSocketClient(
74
72
  self.url,
75
- header=self.headers,
73
+ headers=self.headers,
74
+ is_binary=type(self.protocol) is MessagePackHubProtocol,
75
+ verify_ssl=self.verify_ssl,
76
76
  on_message=self.on_message,
77
77
  on_error=self.on_socket_error,
78
78
  on_close=self.on_close,
79
79
  on_open=self.on_open,
80
+ enable_trace=self.enable_trace
80
81
  )
81
-
82
- self._thread = threading.Thread(
83
- target=lambda: self._ws.run_forever(
84
- sslopt={"cert_reqs": ssl.CERT_NONE}
85
- if not self.verify_ssl else {}
86
- ))
87
- self._thread.daemon = True
88
- self._thread.start()
82
+
83
+ # ToDo
84
+ # if len(self.logger.handlers) > 0:
85
+ # self._ws.enableTrace(self.enable_trace, self.logger.handlers[0])
86
+ self._ws.connect()
89
87
  return True
90
88
 
91
89
  def negotiate(self):
92
90
  negotiate_url = Helpers.get_negotiate_url(self.url)
93
91
  self.logger.debug("Negotiate url:{0}".format(negotiate_url))
94
92
 
95
- response = requests.post(
96
- negotiate_url, headers=self.headers, verify=self.verify_ssl)
97
- self.logger.debug(
98
- "Response status code{0}".format(response.status_code))
93
+ status_code, data = RequestHelpers.post(
94
+ negotiate_url,
95
+ headers=self.headers,
96
+ proxies=self.proxies,
97
+ verify_ssl=self.verify_ssl)
99
98
 
100
- if response.status_code != 200:
101
- raise HubError(response.status_code)\
102
- if response.status_code != 401 else UnAuthorizedHubError()
99
+ self.logger.debug(
100
+ "Response status code{0}".format(status_code))
103
101
 
104
- data = response.json()
102
+ if status_code != 200:
103
+ raise HubError(status_code)\
104
+ if status_code != 401 else UnAuthorizedHubError()
105
105
 
106
106
  if "connectionId" in data.keys():
107
107
  self.url = Helpers.encode_connection_id(
@@ -117,7 +117,6 @@ class WebsocketTransport(BaseTransport):
117
117
  self.token = data["accessToken"]
118
118
  self.headers = {"Authorization": "Bearer " + self.token}
119
119
 
120
-
121
120
  def evaluate_handshake(self, message):
122
121
  self.logger.debug("Evaluating handshake {0}".format(message))
123
122
  msg, messages = self.protocol.decode_handshake(message)
@@ -130,25 +129,21 @@ class WebsocketTransport(BaseTransport):
130
129
  self.connection_checker.start()
131
130
  else:
132
131
  self.logger.error(msg.error)
133
- self.on_socket_error(self._ws, msg.error)
132
+ self.on_socket_error(msg.error)
134
133
  self.stop()
135
134
  self.state = ConnectionState.disconnected
136
135
  return messages
137
136
 
138
- def on_open(self, _):
137
+ def on_open(self):
139
138
  self.logger.debug("-- web socket open --")
140
139
  msg = self.protocol.handshake_message()
141
140
  self.send(msg)
142
141
 
143
- def on_close(self, callback, close_status_code, close_reason):
142
+ def on_close(self):
144
143
  self.logger.debug("-- web socket close --")
145
- self.logger.debug(close_status_code)
146
- self.logger.debug(close_reason)
147
144
  self.state = ConnectionState.disconnected
148
145
  if self._on_close is not None and callable(self._on_close):
149
146
  self._on_close()
150
- if callback is not None and callable(callback):
151
- callback()
152
147
 
153
148
  def on_reconnect(self):
154
149
  self.logger.debug("-- web socket reconnecting --")
@@ -156,11 +151,10 @@ class WebsocketTransport(BaseTransport):
156
151
  if self._on_close is not None and callable(self._on_close):
157
152
  self._on_close()
158
153
 
159
- def on_socket_error(self, app, error):
154
+ def on_socket_error(self, error: Exception):
160
155
  """
161
156
  Args:
162
- _: Required to support websocket-client version equal or greater than 0.58.0
163
- error ([type]): [description]
157
+ error (Exception): websocket error
164
158
 
165
159
  Raises:
166
160
  HubError: [description]
@@ -171,7 +165,7 @@ class WebsocketTransport(BaseTransport):
171
165
  self.logger.error("{0} {1}".format(error, type(error)))
172
166
  self._on_close()
173
167
  self.state = ConnectionState.disconnected
174
- #raise HubError(error)
168
+ # raise HubError(error)
175
169
 
176
170
  def on_message(self, app, raw_message):
177
171
  self.logger.debug("Message received{0}".format(raw_message))
@@ -185,7 +179,7 @@ class WebsocketTransport(BaseTransport):
185
179
  return self._on_message(messages)
186
180
 
187
181
  return []
188
-
182
+
189
183
  return self._on_message(
190
184
  self.protocol.parse_messages(raw_message))
191
185
 
@@ -195,14 +189,12 @@ class WebsocketTransport(BaseTransport):
195
189
  self._ws.send(
196
190
  self.protocol.encode(message),
197
191
  opcode=0x2
198
- if type(self.protocol) == MessagePackHubProtocol else
192
+ if type(self.protocol) is MessagePackHubProtocol else
199
193
  0x1)
200
194
  self.connection_checker.last_message = time.time()
201
195
  if self.reconnection_handler is not None:
202
196
  self.reconnection_handler.reset()
203
- except (
204
- websocket._exceptions.WebSocketConnectionClosedException,
205
- OSError) as ex:
197
+ except OSError as ex:
206
198
  self.handshake_received = False
207
199
  self.logger.warning("Connection closed {0}".format(ex))
208
200
  self.state = ConnectionState.disconnected
@@ -217,7 +209,8 @@ class WebsocketTransport(BaseTransport):
217
209
  raise ex
218
210
 
219
211
  def handle_reconnect(self):
220
- if not self.reconnection_handler.reconnecting and self._on_reconnect is not None and \
212
+ if not self.reconnection_handler.reconnecting \
213
+ and self._on_reconnect is not None and \
221
214
  callable(self._on_reconnect):
222
215
  self._on_reconnect()
223
216
  self.reconnection_handler.reconnecting = True
@@ -227,17 +220,15 @@ class WebsocketTransport(BaseTransport):
227
220
  except Exception as ex:
228
221
  self.logger.error(ex)
229
222
  sleep_time = self.reconnection_handler.next()
230
- threading.Thread(
231
- target=self.deferred_reconnect,
232
- args=(sleep_time,)
233
- ).start()
223
+ self.deferred_reconnect(sleep_time)
234
224
 
235
225
  def deferred_reconnect(self, sleep_time):
236
226
  time.sleep(sleep_time)
237
227
  try:
238
228
  if not self.connection_alive:
239
- self.send(PingMessage())
229
+ if not self.connection_checker.running:
230
+ self.send(PingMessage())
240
231
  except Exception as ex:
241
232
  self.logger.error(ex)
242
233
  self.reconnection_handler.reconnecting = False
243
- self.connection_alive = False
234
+ self.connection_alive = False
@@ -1,19 +1,23 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: signalrcore
3
- Version: 0.9.5
4
- Summary: A Python SignalR Core client(json and messagepack), with invocation auth and two way streaming. Compatible with azure / serverless functions. Also with automatic reconnect and manually reconnect.
3
+ Version: 0.9.6a2
4
+ Summary: A Python SignalR Core client(json and messagepack),with invocation auth and two way streaming.Compatible with azure / serverless functions.Also with automatic reconnect and manually reconnect.
5
5
  Home-page: https://github.com/mandrewcito/signalrcore
6
6
  Author: mandrewcito
7
- Author-email: anbaalo@gmail.com
8
- License: UNKNOWN
7
+ Author-email: signalrcore@mandrewcito.dev
9
8
  Keywords: signalr core client 3.1
10
- Platform: UNKNOWN
11
- Classifier: Programming Language :: Python :: 3.6
9
+ Classifier: Programming Language :: Python :: 3.8
10
+ Classifier: License :: OSI Approved :: MIT License
11
+ Classifier: Operating System :: OS Independent
12
12
  Description-Content-Type: text/markdown
13
13
  License-File: LICENSE
14
- Requires-Dist: requests (>=2.22.0)
15
- Requires-Dist: websocket-client (==1.0.0)
16
- Requires-Dist: msgpack (==1.0.2)
14
+ Requires-Dist: msgpack ==1.0.2
15
+ Provides-Extra: dev
16
+ Requires-Dist: coverage ; extra == 'dev'
17
+ Requires-Dist: flake8 ; extra == 'dev'
18
+ Requires-Dist: pytest ; extra == 'dev'
19
+ Requires-Dist: pytest-cov ; extra == 'dev'
20
+ Requires-Dist: requests ; extra == 'dev'
17
21
 
18
22
  # SignalR core client
19
23
  [![Donate](https://img.shields.io/badge/Donate-PayPal-green.svg?logo=paypal&style=flat-square)](https://www.paypal.me/mandrewcito/1)
@@ -37,24 +41,16 @@ Requires-Dist: msgpack (==1.0.2)
37
41
 
38
42
  # Develop
39
43
 
40
- Test server will be avaiable in [here](https://github.com/mandrewcito/signalrcore-containertestservers) and docker compose is required.
44
+ Test server will be available in [here](https://github.com/mandrewcito/signalrcore-containertestservers) and docker compose is required.
41
45
 
42
46
  ```bash
43
47
  git clone https://github.com/mandrewcito/signalrcore-containertestservers
44
48
  cd signalrcore-containertestservers
45
- docker-compose up
49
+ docker compose up
46
50
  cd ../signalrcore
47
51
  make tests
48
52
  ```
49
53
 
50
- ## Known Issues
51
-
52
- Issues related with closing sockets are inherited from the websocket-client library. Due to these problems i can't update the library to versions higher than websocket-client 0.54.0.
53
- I'm working to solve it but for now its patched (Error number 1. Raises an exception, and then exception is treated for prevent errors).
54
- If I update the websocket library I fall into error number 2, on local machine I can't reproduce it but travis builds fail (sometimes and randomly :()
55
- * [1. Closing socket error](https://github.com/slackapi/python-slackclient/issues/171)
56
- * [2. Random errors closing socket](https://github.com/websocket-client/websocket-client/issues/449)
57
-
58
54
  # A Tiny How To
59
55
 
60
56
  ## Connect to a server without auth
@@ -162,7 +158,7 @@ connection = HubConnectionBuilder()\
162
158
  })\
163
159
  .build()
164
160
  ```
165
- ## Congfiguring skip negotiation
161
+ ## Configuring skip negotiation
166
162
  ```python
167
163
  hub_connection = HubConnectionBuilder() \
168
164
  .with_url("ws://"+server_url, options={
@@ -333,5 +329,3 @@ hub_connection.stop()
333
329
  sys.exit(0)
334
330
 
335
331
  ```
336
-
337
-
@@ -1,12 +1,12 @@
1
1
  signalrcore/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- signalrcore/helpers.py,sha256=uoQCHrT1M2_7fMOYmD-Piw4za2AGz6TENYhe3vvMffw,2756
3
- signalrcore/hub_connection_builder.py,sha256=EBKxRIgVTtlfk3YCQq7F6MWgXqRSNazRNDsAv3lwK4s,8570
2
+ signalrcore/helpers.py,sha256=QELTUh8v-j1qgEo3IXlcTEToR0K3lbZNwrDZpuhtJS0,4422
3
+ signalrcore/hub_connection_builder.py,sha256=A8dtysW5R1_EAJ_GcZZHtea9NLu96dfKMsmmtuY6LRI,9161
4
4
  signalrcore/subject.py,sha256=izH-qzaVPHrK8OgN2ZJ5A_1v4Lx5QtqC_zYfq59hFp4,2112
5
5
  signalrcore/hub/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
6
  signalrcore/hub/auth_hub_connection.py,sha256=YVsmRhGhG8CYi7egnYbFJXPB7dDiPOnwX45dQg8MhUA,964
7
- signalrcore/hub/base_hub_connection.py,sha256=qyVCI57w_jyoIgTcYTzq5EfEnSPLGbI1C7U8Eak4RRY,9673
8
- signalrcore/hub/errors.py,sha256=CxyoYj7B8-5OUBhT2QBYFcDzmOvYCdkp42MOZls8xkw,176
9
- signalrcore/hub/handlers.py,sha256=g85bQ6Sr2-KHzMJXHBJdYqeALGHy-Z5GyGrLVGqVSLg,1928
7
+ signalrcore/hub/base_hub_connection.py,sha256=dj-uXjGaPNPA7lGmIscwsah_Y6BeukpbdEwKGG5_UJk,9939
8
+ signalrcore/hub/errors.py,sha256=EDJgMT-ZpWc1VIRA--Qjahg2LBK0u0mM5V5UX7-i-XQ,180
9
+ signalrcore/hub/handlers.py,sha256=-f6OLQ9AMwGqE7Gh-84oHf0bTgUVsSlFuRg_T0ff_T8,1914
10
10
  signalrcore/messages/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
11
11
  signalrcore/messages/base_message.py,sha256=AAydVr-g85U2xthOM4jm2hqHQ3ZBaOSiO0hmXlqCEpI,447
12
12
  signalrcore/messages/cancel_invocation_message.py,sha256=CLsAom4Ubf3bn8HroEOzgiye_6VI9RnjgJmxtwqshbo,647
@@ -21,28 +21,30 @@ signalrcore/messages/handshake/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5
21
21
  signalrcore/messages/handshake/request.py,sha256=zNM8PZ4m4W1OSlEnXCxjPLnlYNXPF7yrToDDPxdcb9c,152
22
22
  signalrcore/messages/handshake/response.py,sha256=ekQx_MX9ZTxHgDa7uiKAivBjky8xVMV5ljjf-Rpeo5w,103
23
23
  signalrcore/protocol/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
24
- signalrcore/protocol/base_hub_protocol.py,sha256=B2_kqssL9Um-h2Oplu2vRfo8vsOAjp-QeSidHdmX4Hw,2991
24
+ signalrcore/protocol/base_hub_protocol.py,sha256=6eSUD84R97C7eRfNEzakYVDANg-PEnw2tJ3LhdkPK9k,3000
25
25
  signalrcore/protocol/json_hub_protocol.py,sha256=aJ5rLdhLt3ijW_G1aATtTFL-nbSa3cZFlv2yzcox3hg,1654
26
- signalrcore/protocol/messagepack_protocol.py,sha256=ZS-QqOyk_yPrKFBb_F4KM3rYJT1M_IAxzQTtjUMs-q0,6419
26
+ signalrcore/protocol/messagepack_protocol.py,sha256=BS5pd5bDk8GIOcWJZptFPtlwVPU5Wp9w2F-4Sg19vpY,7054
27
27
  signalrcore/protocol/handshake/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
28
28
  signalrcore/transport/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
29
- signalrcore/transport/base_transport.py,sha256=KXPzdgQkxwcj2Unm4WRvoGMpGKao01VJZAyQ0HvegiU,1124
29
+ signalrcore/transport/base_transport.py,sha256=1LVw5kNxU0BBAeNA5smkV2vnhGKq3uD42EoPo8iO8gU,1134
30
30
  signalrcore/transport/websockets/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
31
31
  signalrcore/transport/websockets/connection.py,sha256=mBaZeNxcqWjDlNOnMWk8Pp7vu3g3_wY5oQPUdIL7L3E,140
32
32
  signalrcore/transport/websockets/reconnection.py,sha256=y3SSYLl3VFXLVNDtTdojBbAvMDzHoiXJod7wu-L9D3w,2680
33
- signalrcore/transport/websockets/websocket_transport.py,sha256=ym7ZakkOyXoBwnBx_HC5xw5IQB1_2DlIdOoVP8b45CE,8907
33
+ signalrcore/transport/websockets/websocket_client.py,sha256=h2Ve7r0rEjesblsa8TnzijRDA4Cp-GTqQCp0ysau_Fg,7933
34
+ signalrcore/transport/websockets/websocket_transport.py,sha256=2uuWYfINegW01PgaS86hsEEg-1hcKBpFiikLrtGcgfQ,8425
34
35
  test/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
35
- test/base_test_case.py,sha256=k_zqhAZRmPkzKizVkVsn-A4fpWxNEqg9kJjg036OTD4,1835
36
- test/client_streaming_test.py,sha256=zKfle7J0kg5LzpzaL13WXdRb7xdZCILLcXHCV2GZhNw,1002
37
- test/configuration_test.py,sha256=OLeBfnS3CM96Jfb2q1oJ-J3xAc8rHMts53a2tbY6FP0,2164
38
- test/open_close_test.py,sha256=g3YlSYS-jhpj6mdLLqPoigXF1CqGlR-bFn1ThIvNCwk,1566
39
- test/reconnection_test.py,sha256=O7hc5NG1ou3zgK9C4I1b37vxk3Pas5T6nNL1rTrEJ5c,3992
40
- test/send_auth_errors_test.py,sha256=PIFmcQ_y1iZ1cMiDt-QRMhFCvindxvcNiS1RTksyA1o,1833
41
- test/send_auth_test.py,sha256=rTwF2sizB_DZpU4gulEqfsHAfIBOciMMN1DwzgZb2Dg,2733
42
- test/send_test.py,sha256=hTSmTsJmn2YjompPaVCFU0z61AF0lp32Rrp8Fywersg,5523
43
- test/streaming_test.py,sha256=gaNF4rd0Z4ijxsFcCwhW_8JrbHxKBdDHWpoPCNSgfzU,1977
44
- signalrcore-0.9.5.dist-info/LICENSE,sha256=zlgZo2qli0c9PLoPObfeGy9yEXuQOV2HF26LykBg5Ko,1101
45
- signalrcore-0.9.5.dist-info/METADATA,sha256=V_kY9TULRO2_1jwPErZascw9IZFo3MRiF6jeJ9Yuqno,10552
46
- signalrcore-0.9.5.dist-info/WHEEL,sha256=G16H4A3IeoQmnOrYV4ueZGKSjhipXx8zc8nu9FGlvMA,92
47
- signalrcore-0.9.5.dist-info/top_level.txt,sha256=I28KSOVJS0rNgMCI8E8W-13gvoCGHkmwc6z4NSrQlo0,17
48
- signalrcore-0.9.5.dist-info/RECORD,,
36
+ test/base_test_case.py,sha256=HDTCbf4_xjeA0rX9vj30B3sGBetfA_u728gcQ48CTNM,1840
37
+ test/client_streaming_test.py,sha256=qXmzj1KQkAbGXj9nls3p0-9q6PirUj78f40AQE7MIX8,836
38
+ test/configuration_test.py,sha256=KBBObisq2RvOrDM8OW7KzQnOPgJmCyv-Ndr2ykPjS8U,2222
39
+ test/open_close_test.py,sha256=EKedyOWS3q86LzNQCJ8KaYoXEusAi8vXCW8K2hzD5o8,1665
40
+ test/reconnection_test.py,sha256=dvbWplOE5gU7Ve_yNb9TmmrKoUl0KgsI8ZQPN8UXsJw,4251
41
+ test/send_auth_errors_test.py,sha256=warY87prADkdh1PL3_hmtGQt8j_wqFz1puiYj-Z2SLk,1808
42
+ test/send_auth_test.py,sha256=R1tS6NCYdr9fmVMspQmZDmHbQpTLUrDnzukjgE-blO4,2733
43
+ test/send_test.py,sha256=lKOt4OC84GMN4wunpfq_GU-nQQ_N5cgkGJj-Da3u1s4,5942
44
+ test/streaming_test.py,sha256=GM7BpQwrP27Pjmhdt3vQUTAZyWyoyA2QThPymY7s3Ao,1839
45
+ test/subscribe_test.py,sha256=fQ5W_l9kX9dp4khwo6U4-8hEDYLLD5p9FdgwTeOAhDg,505
46
+ signalrcore-0.9.6a2.dist-info/LICENSE,sha256=zlgZo2qli0c9PLoPObfeGy9yEXuQOV2HF26LykBg5Ko,1101
47
+ signalrcore-0.9.6a2.dist-info/METADATA,sha256=-AvuZOscKnfnrr4ZjjBcRrg7stCPbWM_hS1P-jOnXTs,10087
48
+ signalrcore-0.9.6a2.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
49
+ signalrcore-0.9.6a2.dist-info/top_level.txt,sha256=I28KSOVJS0rNgMCI8E8W-13gvoCGHkmwc6z4NSrQlo0,17
50
+ signalrcore-0.9.6a2.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.37.1)
2
+ Generator: bdist_wheel (0.42.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5