signalrcore 0.8.7__tar.gz → 0.9.6b1__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.
- signalrcore-0.9.6b1/LICENSE +21 -0
- signalrcore-0.9.6b1/MANIFEST.in +1 -0
- signalrcore-0.9.6b1/PKG-INFO +342 -0
- {signalrcore-0.8.7 → signalrcore-0.9.6b1}/README.md +38 -32
- {signalrcore-0.8.7 → signalrcore-0.9.6b1}/setup.cfg +0 -0
- signalrcore-0.9.6b1/setup.py +38 -0
- {signalrcore-0.8.7 → signalrcore-0.9.6b1}/signalrcore/__init__.py +0 -0
- {signalrcore-0.8.7 → signalrcore-0.9.6b1}/signalrcore/helpers.py +75 -13
- {signalrcore-0.8.7 → signalrcore-0.9.6b1}/signalrcore/hub/__init__.py +0 -0
- signalrcore-0.9.6b1/signalrcore/hub/auth_hub_connection.py +25 -0
- signalrcore-0.9.6b1/signalrcore/hub/base_hub_connection.py +296 -0
- signalrcore-0.9.6b1/signalrcore/hub/errors.py +12 -0
- signalrcore-0.9.6b1/signalrcore/hub/handlers.py +51 -0
- signalrcore-0.9.6b1/signalrcore/hub_connection_builder.py +266 -0
- {signalrcore-0.8.7 → signalrcore-0.9.6b1}/signalrcore/messages/__init__.py +0 -0
- {signalrcore-0.8.7 → signalrcore-0.9.6b1}/signalrcore/messages/base_message.py +3 -2
- {signalrcore-0.8.7 → signalrcore-0.9.6b1}/signalrcore/messages/cancel_invocation_message.py +5 -4
- {signalrcore-0.8.7 → signalrcore-0.9.6b1}/signalrcore/messages/close_message.py +5 -4
- {signalrcore-0.8.7 → signalrcore-0.9.6b1}/signalrcore/messages/completion_message.py +15 -11
- {signalrcore-0.8.7 → signalrcore-0.9.6b1}/signalrcore/messages/handshake/__init__.py +0 -0
- {signalrcore-0.8.7 → signalrcore-0.9.6b1}/signalrcore/messages/handshake/request.py +0 -0
- {signalrcore-0.8.7 → signalrcore-0.9.6b1}/signalrcore/messages/handshake/response.py +0 -0
- {signalrcore-0.8.7 → signalrcore-0.9.6b1}/signalrcore/messages/invocation_message.py +20 -12
- {signalrcore-0.8.7 → signalrcore-0.9.6b1}/signalrcore/messages/message_type.py +1 -5
- {signalrcore-0.8.7 → signalrcore-0.9.6b1}/signalrcore/messages/ping_message.py +4 -3
- {signalrcore-0.8.7 → signalrcore-0.9.6b1}/signalrcore/messages/stream_invocation_message.py +11 -6
- {signalrcore-0.8.7 → signalrcore-0.9.6b1}/signalrcore/messages/stream_item_message.py +7 -5
- {signalrcore-0.8.7 → signalrcore-0.9.6b1}/signalrcore/protocol/__init__.py +0 -0
- signalrcore-0.9.6b1/signalrcore/protocol/base_hub_protocol.py +64 -0
- {signalrcore-0.8.7 → signalrcore-0.9.6b1}/signalrcore/protocol/handshake/__init__.py +0 -0
- {signalrcore-0.8.7 → signalrcore-0.9.6b1}/signalrcore/protocol/json_hub_protocol.py +7 -5
- signalrcore-0.9.6b1/signalrcore/protocol/messagepack_protocol.py +186 -0
- signalrcore-0.9.6b1/signalrcore/subject.py +68 -0
- {signalrcore-0.8.7/test → signalrcore-0.9.6b1/signalrcore/transport}/__init__.py +0 -0
- signalrcore-0.9.6b1/signalrcore/transport/base_reconnection.py +9 -0
- signalrcore-0.9.6b1/signalrcore/transport/base_transport.py +87 -0
- signalrcore-0.9.6b1/signalrcore/transport/websockets/__init__.py +0 -0
- {signalrcore-0.8.7/signalrcore/hub → signalrcore-0.9.6b1/signalrcore/transport/websockets}/reconnection.py +9 -8
- signalrcore-0.9.6b1/signalrcore/transport/websockets/websocket_client.py +292 -0
- signalrcore-0.9.6b1/signalrcore/transport/websockets/websocket_transport.py +240 -0
- signalrcore-0.9.6b1/signalrcore.egg-info/PKG-INFO +342 -0
- {signalrcore-0.8.7 → signalrcore-0.9.6b1}/signalrcore.egg-info/SOURCES.txt +12 -3
- {signalrcore-0.8.7 → signalrcore-0.9.6b1}/signalrcore.egg-info/dependency_links.txt +0 -0
- signalrcore-0.9.6b1/signalrcore.egg-info/requires.txt +8 -0
- {signalrcore-0.8.7 → signalrcore-0.9.6b1}/signalrcore.egg-info/top_level.txt +0 -0
- signalrcore-0.9.6b1/test/__init__.py +0 -0
- {signalrcore-0.8.7 → signalrcore-0.9.6b1}/test/base_test_case.py +63 -68
- signalrcore-0.9.6b1/test/client_streaming_test.py +28 -0
- {signalrcore-0.8.7 → signalrcore-0.9.6b1}/test/configuration_test.py +64 -62
- signalrcore-0.9.6b1/test/open_close_test.py +80 -0
- signalrcore-0.9.6b1/test/reconnection_test.py +158 -0
- signalrcore-0.9.6b1/test/send_auth_errors_test.py +60 -0
- {signalrcore-0.8.7 → signalrcore-0.9.6b1}/test/send_auth_test.py +90 -68
- signalrcore-0.9.6b1/test/send_test.py +201 -0
- {signalrcore-0.8.7 → signalrcore-0.9.6b1}/test/streaming_test.py +67 -60
- signalrcore-0.9.6b1/test/subscribe_test.py +18 -0
- signalrcore-0.8.7/PKG-INFO +0 -316
- signalrcore-0.8.7/setup.py +0 -24
- signalrcore-0.8.7/signalrcore/hub/auth_hub_connection.py +0 -30
- signalrcore-0.8.7/signalrcore/hub/base_hub_connection.py +0 -330
- signalrcore-0.8.7/signalrcore/hub/connection_state.py +0 -12
- signalrcore-0.8.7/signalrcore/hub/errors.py +0 -6
- signalrcore-0.8.7/signalrcore/hub_connection_builder.py +0 -212
- signalrcore-0.8.7/signalrcore/protocol/base_hub_protocol.py +0 -86
- signalrcore-0.8.7/signalrcore/protocol/messagepack_protocol.py +0 -31
- signalrcore-0.8.7/signalrcore/subject.py +0 -45
- signalrcore-0.8.7/signalrcore.egg-info/PKG-INFO +0 -316
- signalrcore-0.8.7/signalrcore.egg-info/requires.txt +0 -2
- signalrcore-0.8.7/test/client_streaming_test.py +0 -25
- signalrcore-0.8.7/test/open_close_test.py +0 -39
- signalrcore-0.8.7/test/reconnection_test.py +0 -48
- signalrcore-0.8.7/test/send_auth_errors_test.py +0 -49
- signalrcore-0.8.7/test/send_test.py +0 -88
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2019 Andrés Baamonde Lozano
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
include LICENSE
|
|
@@ -0,0 +1,342 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: signalrcore
|
|
3
|
+
Version: 0.9.6b1
|
|
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
|
+
Home-page: https://github.com/mandrewcito/signalrcore
|
|
6
|
+
Author: mandrewcito
|
|
7
|
+
Author-email: signalrcore@mandrewcito.dev
|
|
8
|
+
Keywords: signalr core client 3.1
|
|
9
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
10
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
11
|
+
Classifier: Operating System :: OS Independent
|
|
12
|
+
Description-Content-Type: text/markdown
|
|
13
|
+
License-File: LICENSE
|
|
14
|
+
Requires-Dist: msgpack==1.0.2
|
|
15
|
+
Provides-Extra: dev
|
|
16
|
+
Requires-Dist: requests; extra == "dev"
|
|
17
|
+
Requires-Dist: flake8; extra == "dev"
|
|
18
|
+
Requires-Dist: coverage; extra == "dev"
|
|
19
|
+
Requires-Dist: pytest; extra == "dev"
|
|
20
|
+
Requires-Dist: pytest-cov; extra == "dev"
|
|
21
|
+
Dynamic: author
|
|
22
|
+
Dynamic: author-email
|
|
23
|
+
Dynamic: classifier
|
|
24
|
+
Dynamic: description
|
|
25
|
+
Dynamic: description-content-type
|
|
26
|
+
Dynamic: home-page
|
|
27
|
+
Dynamic: keywords
|
|
28
|
+
Dynamic: license-file
|
|
29
|
+
Dynamic: provides-extra
|
|
30
|
+
Dynamic: requires-dist
|
|
31
|
+
Dynamic: summary
|
|
32
|
+
|
|
33
|
+
# SignalR core client
|
|
34
|
+
[](https://www.paypal.me/mandrewcito/1)
|
|
35
|
+

|
|
36
|
+
[](https://pepy.tech/project/signalrcore/month)
|
|
37
|
+
[](https://pepy.tech/project/signalrcore)
|
|
38
|
+

|
|
39
|
+

|
|
40
|
+

|
|
41
|
+
|
|
42
|
+

|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
# Links
|
|
46
|
+
|
|
47
|
+
* [Dev to posts with library examples and implementation](https://dev.to/mandrewcito/singlar-core-python-client-58e7)
|
|
48
|
+
|
|
49
|
+
* [Pypi](https://pypi.org/project/signalrcore/)
|
|
50
|
+
|
|
51
|
+
* [Wiki - This Doc](https://mandrewcito.github.io/signalrcore/)
|
|
52
|
+
|
|
53
|
+
# Develop
|
|
54
|
+
|
|
55
|
+
Test server will be available in [here](https://github.com/mandrewcito/signalrcore-containertestservers) and docker compose is required.
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
git clone https://github.com/mandrewcito/signalrcore-containertestservers
|
|
59
|
+
cd signalrcore-containertestservers
|
|
60
|
+
docker compose up
|
|
61
|
+
cd ../signalrcore
|
|
62
|
+
make tests
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
# A Tiny How To
|
|
66
|
+
|
|
67
|
+
## Connect to a server without auth
|
|
68
|
+
|
|
69
|
+
```python
|
|
70
|
+
hub_connection = HubConnectionBuilder()\
|
|
71
|
+
.with_url(server_url)\
|
|
72
|
+
.configure_logging(logging.DEBUG)\
|
|
73
|
+
.with_automatic_reconnect({
|
|
74
|
+
"type": "raw",
|
|
75
|
+
"keep_alive_interval": 10,
|
|
76
|
+
"reconnect_interval": 5,
|
|
77
|
+
"max_attempts": 5
|
|
78
|
+
}).build()
|
|
79
|
+
```
|
|
80
|
+
## Connect to a server with auth
|
|
81
|
+
|
|
82
|
+
login_function must provide auth token
|
|
83
|
+
|
|
84
|
+
```python
|
|
85
|
+
hub_connection = HubConnectionBuilder()\
|
|
86
|
+
.with_url(server_url,
|
|
87
|
+
options={
|
|
88
|
+
"access_token_factory": login_function,
|
|
89
|
+
"headers": {
|
|
90
|
+
"mycustomheader": "mycustomheadervalue"
|
|
91
|
+
}
|
|
92
|
+
})\
|
|
93
|
+
.configure_logging(logging.DEBUG)\
|
|
94
|
+
.with_automatic_reconnect({
|
|
95
|
+
"type": "raw",
|
|
96
|
+
"keep_alive_interval": 10,
|
|
97
|
+
"reconnect_interval": 5,
|
|
98
|
+
"max_attempts": 5
|
|
99
|
+
}).build()
|
|
100
|
+
```
|
|
101
|
+
### Unauthorized errors
|
|
102
|
+
A login function must provide an error controller if authorization fails. When connection starts, if authorization fails exception will be propagated.
|
|
103
|
+
|
|
104
|
+
```python
|
|
105
|
+
def login(self):
|
|
106
|
+
response = requests.post(
|
|
107
|
+
self.login_url,
|
|
108
|
+
json={
|
|
109
|
+
"username": self.email,
|
|
110
|
+
"password": self.password
|
|
111
|
+
},verify=False)
|
|
112
|
+
if response.status_code == 200:
|
|
113
|
+
return response.json()["token"]
|
|
114
|
+
raise requests.exceptions.ConnectionError()
|
|
115
|
+
|
|
116
|
+
hub_connection.start() # this code will raise requests.exceptions.ConnectionError() if auth fails
|
|
117
|
+
```
|
|
118
|
+
## Configure logging
|
|
119
|
+
|
|
120
|
+
```python
|
|
121
|
+
HubConnectionBuilder()\
|
|
122
|
+
.with_url(server_url,
|
|
123
|
+
.configure_logging(logging.DEBUG)
|
|
124
|
+
...
|
|
125
|
+
```
|
|
126
|
+
## Configure socket trace
|
|
127
|
+
```python
|
|
128
|
+
HubConnectionBuilder()\
|
|
129
|
+
.with_url(server_url,
|
|
130
|
+
.configure_logging(logging.DEBUG, socket_trace=True)
|
|
131
|
+
...
|
|
132
|
+
```
|
|
133
|
+
## Configure your own handler
|
|
134
|
+
```python
|
|
135
|
+
import logging
|
|
136
|
+
handler = logging.StreamHandler()
|
|
137
|
+
handler.setLevel(logging.DEBUG)
|
|
138
|
+
hub_connection = HubConnectionBuilder()\
|
|
139
|
+
.with_url(server_url, options={"verify_ssl": False}) \
|
|
140
|
+
.configure_logging(logging.DEBUG, socket_trace=True, handler=handler)
|
|
141
|
+
...
|
|
142
|
+
```
|
|
143
|
+
## Configuring reconnection
|
|
144
|
+
After reaching max_attempts an exeption will be thrown and on_disconnect event will be fired.
|
|
145
|
+
```python
|
|
146
|
+
hub_connection = HubConnectionBuilder()\
|
|
147
|
+
.with_url(server_url)\
|
|
148
|
+
...
|
|
149
|
+
.build()
|
|
150
|
+
```
|
|
151
|
+
## Configuring additional headers
|
|
152
|
+
```python
|
|
153
|
+
hub_connection = HubConnectionBuilder()\
|
|
154
|
+
.with_url(server_url,
|
|
155
|
+
options={
|
|
156
|
+
"headers": {
|
|
157
|
+
"mycustomheader": "mycustomheadervalue"
|
|
158
|
+
}
|
|
159
|
+
})
|
|
160
|
+
...
|
|
161
|
+
.build()
|
|
162
|
+
```
|
|
163
|
+
## Configuring additional querystring parameters
|
|
164
|
+
```python
|
|
165
|
+
server_url ="http.... /?myquerystringparam=134&foo=bar"
|
|
166
|
+
connection = HubConnectionBuilder()\
|
|
167
|
+
.with_url(server_url,
|
|
168
|
+
options={
|
|
169
|
+
})\
|
|
170
|
+
.build()
|
|
171
|
+
```
|
|
172
|
+
## Configuring skip negotiation
|
|
173
|
+
```python
|
|
174
|
+
hub_connection = HubConnectionBuilder() \
|
|
175
|
+
.with_url("ws://"+server_url, options={
|
|
176
|
+
"verify_ssl": False,
|
|
177
|
+
"skip_negotiation": False,
|
|
178
|
+
"headers": {
|
|
179
|
+
}
|
|
180
|
+
}) \
|
|
181
|
+
.configure_logging(logging.DEBUG, socket_trace=True, handler=handler) \
|
|
182
|
+
.build()
|
|
183
|
+
|
|
184
|
+
```
|
|
185
|
+
## Configuring ping(keep alive)
|
|
186
|
+
|
|
187
|
+
keep_alive_interval sets the seconds of ping message
|
|
188
|
+
|
|
189
|
+
```python
|
|
190
|
+
hub_connection = HubConnectionBuilder()\
|
|
191
|
+
.with_url(server_url)\
|
|
192
|
+
.configure_logging(logging.DEBUG)\
|
|
193
|
+
.with_automatic_reconnect({
|
|
194
|
+
"type": "raw",
|
|
195
|
+
"keep_alive_interval": 10,
|
|
196
|
+
"reconnect_interval": 5,
|
|
197
|
+
"max_attempts": 5
|
|
198
|
+
}).build()
|
|
199
|
+
```
|
|
200
|
+
## Configuring logging
|
|
201
|
+
```python
|
|
202
|
+
hub_connection = HubConnectionBuilder()\
|
|
203
|
+
.with_url(server_url)\
|
|
204
|
+
.configure_logging(logging.DEBUG)\
|
|
205
|
+
.with_automatic_reconnect({
|
|
206
|
+
"type": "raw",
|
|
207
|
+
"keep_alive_interval": 10,
|
|
208
|
+
"reconnect_interval": 5,
|
|
209
|
+
"max_attempts": 5
|
|
210
|
+
}).build()
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
## Configure messagepack
|
|
214
|
+
|
|
215
|
+
```python
|
|
216
|
+
from signalrcore.protocol.messagepack_protocol import MessagePackHubProtocol
|
|
217
|
+
|
|
218
|
+
HubConnectionBuilder()\
|
|
219
|
+
.with_url(self.server_url, options={"verify_ssl":False})\
|
|
220
|
+
...
|
|
221
|
+
.with_hub_protocol(MessagePackHubProtocol())\
|
|
222
|
+
...
|
|
223
|
+
.build()
|
|
224
|
+
```
|
|
225
|
+
## Events
|
|
226
|
+
|
|
227
|
+
### On Connect / On Disconnect
|
|
228
|
+
on_open - fires when connection is opened and ready to send messages
|
|
229
|
+
on_close - fires when connection is closed
|
|
230
|
+
```python
|
|
231
|
+
hub_connection.on_open(lambda: print("connection opened and handshake received ready to send messages"))
|
|
232
|
+
hub_connection.on_close(lambda: print("connection closed"))
|
|
233
|
+
|
|
234
|
+
```
|
|
235
|
+
### On Hub Error (Hub Exceptions ...)
|
|
236
|
+
```
|
|
237
|
+
hub_connection.on_error(lambda data: print(f"An exception was thrown closed{data.error}"))
|
|
238
|
+
```
|
|
239
|
+
### Register an operation
|
|
240
|
+
ReceiveMessage - signalr method
|
|
241
|
+
print - function that has as parameters args of signalr method
|
|
242
|
+
```python
|
|
243
|
+
hub_connection.on("ReceiveMessage", print)
|
|
244
|
+
```
|
|
245
|
+
## Sending messages
|
|
246
|
+
SendMessage - signalr method
|
|
247
|
+
username, message - parameters of signalrmethod
|
|
248
|
+
```python
|
|
249
|
+
hub_connection.send("SendMessage", [username, message])
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
## Sending messages with callback
|
|
253
|
+
SendMessage - signalr method
|
|
254
|
+
username, message - parameters of signalrmethod
|
|
255
|
+
```python
|
|
256
|
+
send_callback_received = threading.Lock()
|
|
257
|
+
send_callback_received.acquire()
|
|
258
|
+
self.connection.send(
|
|
259
|
+
"SendMessage", # Method
|
|
260
|
+
[self.username, self.message], # Params
|
|
261
|
+
lambda m: send_callback_received.release()) # Callback
|
|
262
|
+
if not send_callback_received.acquire(timeout=1):
|
|
263
|
+
raise ValueError("CALLBACK NOT RECEIVED")
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
## Requesting streaming (Server to client)
|
|
267
|
+
```python
|
|
268
|
+
hub_connection.stream(
|
|
269
|
+
"Counter",
|
|
270
|
+
[len(self.items), 500]).subscribe({
|
|
271
|
+
"next": self.on_next,
|
|
272
|
+
"complete": self.on_complete,
|
|
273
|
+
"error": self.on_error
|
|
274
|
+
})
|
|
275
|
+
```
|
|
276
|
+
## Client side Streaming
|
|
277
|
+
```python
|
|
278
|
+
from signalrcore.subject import Subject
|
|
279
|
+
|
|
280
|
+
subject = Subject()
|
|
281
|
+
|
|
282
|
+
# Start Streaming
|
|
283
|
+
hub_connection.send("UploadStream", subject)
|
|
284
|
+
|
|
285
|
+
# Each iteration
|
|
286
|
+
subject.next(str(iteration))
|
|
287
|
+
|
|
288
|
+
# End streaming
|
|
289
|
+
subject.complete()
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
# Full Examples
|
|
293
|
+
|
|
294
|
+
Examples will be avaiable [here](https://github.com/mandrewcito/signalrcore/tree/master/test/examples)
|
|
295
|
+
It were developed using package from [aspnet core - SignalRChat](https://codeload.github.com/aspnet/Docs/zip/master)
|
|
296
|
+
|
|
297
|
+
## Chat example
|
|
298
|
+
A mini example could be something like this:
|
|
299
|
+
|
|
300
|
+
```python
|
|
301
|
+
import logging
|
|
302
|
+
import sys
|
|
303
|
+
from signalrcore.hub_connection_builder import HubConnectionBuilder
|
|
304
|
+
|
|
305
|
+
|
|
306
|
+
def input_with_default(input_text, default_value):
|
|
307
|
+
value = input(input_text.format(default_value))
|
|
308
|
+
return default_value if value is None or value.strip() == "" else value
|
|
309
|
+
|
|
310
|
+
|
|
311
|
+
server_url = input_with_default('Enter your server url(default: {0}): ', "wss://localhost:44376/chatHub")
|
|
312
|
+
username = input_with_default('Enter your username (default: {0}): ', "mandrewcito")
|
|
313
|
+
handler = logging.StreamHandler()
|
|
314
|
+
handler.setLevel(logging.DEBUG)
|
|
315
|
+
hub_connection = HubConnectionBuilder()\
|
|
316
|
+
.with_url(server_url, options={"verify_ssl": False}) \
|
|
317
|
+
.configure_logging(logging.DEBUG, socket_trace=True, handler=handler) \
|
|
318
|
+
.with_automatic_reconnect({
|
|
319
|
+
"type": "interval",
|
|
320
|
+
"keep_alive_interval": 10,
|
|
321
|
+
"intervals": [1, 3, 5, 6, 7, 87, 3]
|
|
322
|
+
}).build()
|
|
323
|
+
|
|
324
|
+
hub_connection.on_open(lambda: print("connection opened and handshake received ready to send messages"))
|
|
325
|
+
hub_connection.on_close(lambda: print("connection closed"))
|
|
326
|
+
|
|
327
|
+
hub_connection.on("ReceiveMessage", print)
|
|
328
|
+
hub_connection.start()
|
|
329
|
+
message = None
|
|
330
|
+
|
|
331
|
+
# Do login
|
|
332
|
+
|
|
333
|
+
while message != "exit()":
|
|
334
|
+
message = input(">> ")
|
|
335
|
+
if message is not None and message != "" and message != "exit()":
|
|
336
|
+
hub_connection.send("SendMessage", [username, message])
|
|
337
|
+
|
|
338
|
+
hub_connection.stop()
|
|
339
|
+
|
|
340
|
+
sys.exit(0)
|
|
341
|
+
|
|
342
|
+
```
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
# SignalR core client
|
|
2
2
|
[](https://www.paypal.me/mandrewcito/1)
|
|
3
3
|

|
|
4
|
-
](https://pepy.tech/project/signalrcore/month)
|
|
5
|
+
[](https://pepy.tech/project/signalrcore)
|
|
5
6
|

|
|
6
7
|

|
|
7
|
-

|
|
8
8
|

|
|
9
9
|
|
|
10
10
|

|
|
@@ -14,31 +14,23 @@
|
|
|
14
14
|
|
|
15
15
|
* [Dev to posts with library examples and implementation](https://dev.to/mandrewcito/singlar-core-python-client-58e7)
|
|
16
16
|
|
|
17
|
-
* [
|
|
17
|
+
* [Pypi](https://pypi.org/project/signalrcore/)
|
|
18
18
|
|
|
19
19
|
* [Wiki - This Doc](https://mandrewcito.github.io/signalrcore/)
|
|
20
20
|
|
|
21
21
|
# Develop
|
|
22
22
|
|
|
23
|
-
Test server will be
|
|
23
|
+
Test server will be available in [here](https://github.com/mandrewcito/signalrcore-containertestservers) and docker compose is required.
|
|
24
24
|
|
|
25
25
|
```bash
|
|
26
26
|
git clone https://github.com/mandrewcito/signalrcore-containertestservers
|
|
27
27
|
cd signalrcore-containertestservers
|
|
28
|
-
docker
|
|
28
|
+
docker compose up
|
|
29
29
|
cd ../signalrcore
|
|
30
30
|
make tests
|
|
31
31
|
```
|
|
32
32
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
Issues related with closing socket inherited from websocket-client library. Due this problems i cant update library to versions higher than websocket-client 0.54.0.
|
|
36
|
-
I'm working for solve it, for now its patched (Error number 1. Raises an exception, and then exception is treated for prevent errors).
|
|
37
|
-
If i update weboscket library i fall into error number 2, on local machine i cant reproduce it but on travis builds fails (sometimes and randomly :()
|
|
38
|
-
* [1. Closing socket error](https://github.com/slackapi/python-slackclient/issues/171)
|
|
39
|
-
* [2. Random errors closing socket](https://github.com/websocket-client/websocket-client/issues/449)
|
|
40
|
-
|
|
41
|
-
# A tiny How To
|
|
33
|
+
# A Tiny How To
|
|
42
34
|
|
|
43
35
|
## Connect to a server without auth
|
|
44
36
|
|
|
@@ -74,8 +66,8 @@ hub_connection = HubConnectionBuilder()\
|
|
|
74
66
|
"max_attempts": 5
|
|
75
67
|
}).build()
|
|
76
68
|
```
|
|
77
|
-
### Unauthorized
|
|
78
|
-
A login function must provide
|
|
69
|
+
### Unauthorized errors
|
|
70
|
+
A login function must provide an error controller if authorization fails. When connection starts, if authorization fails exception will be propagated.
|
|
79
71
|
|
|
80
72
|
```python
|
|
81
73
|
def login(self):
|
|
@@ -106,8 +98,8 @@ HubConnectionBuilder()\
|
|
|
106
98
|
.configure_logging(logging.DEBUG, socket_trace=True)
|
|
107
99
|
...
|
|
108
100
|
```
|
|
109
|
-
|
|
110
|
-
|
|
101
|
+
## Configure your own handler
|
|
102
|
+
```python
|
|
111
103
|
import logging
|
|
112
104
|
handler = logging.StreamHandler()
|
|
113
105
|
handler.setLevel(logging.DEBUG)
|
|
@@ -116,16 +108,15 @@ hub_connection = HubConnectionBuilder()\
|
|
|
116
108
|
.configure_logging(logging.DEBUG, socket_trace=True, handler=handler)
|
|
117
109
|
...
|
|
118
110
|
```
|
|
119
|
-
## Configuring
|
|
120
|
-
After reaching
|
|
121
|
-
fired.
|
|
111
|
+
## Configuring reconnection
|
|
112
|
+
After reaching max_attempts an exeption will be thrown and on_disconnect event will be fired.
|
|
122
113
|
```python
|
|
123
114
|
hub_connection = HubConnectionBuilder()\
|
|
124
115
|
.with_url(server_url)\
|
|
125
116
|
...
|
|
126
117
|
.build()
|
|
127
118
|
```
|
|
128
|
-
## Configuring
|
|
119
|
+
## Configuring additional headers
|
|
129
120
|
```python
|
|
130
121
|
hub_connection = HubConnectionBuilder()\
|
|
131
122
|
.with_url(server_url,
|
|
@@ -137,7 +128,7 @@ hub_connection = HubConnectionBuilder()\
|
|
|
137
128
|
...
|
|
138
129
|
.build()
|
|
139
130
|
```
|
|
140
|
-
## Configuring
|
|
131
|
+
## Configuring additional querystring parameters
|
|
141
132
|
```python
|
|
142
133
|
server_url ="http.... /?myquerystringparam=134&foo=bar"
|
|
143
134
|
connection = HubConnectionBuilder()\
|
|
@@ -146,7 +137,7 @@ connection = HubConnectionBuilder()\
|
|
|
146
137
|
})\
|
|
147
138
|
.build()
|
|
148
139
|
```
|
|
149
|
-
##
|
|
140
|
+
## Configuring skip negotiation
|
|
150
141
|
```python
|
|
151
142
|
hub_connection = HubConnectionBuilder() \
|
|
152
143
|
.with_url("ws://"+server_url, options={
|
|
@@ -161,7 +152,7 @@ hub_connection = HubConnectionBuilder() \
|
|
|
161
152
|
```
|
|
162
153
|
## Configuring ping(keep alive)
|
|
163
154
|
|
|
164
|
-
keep_alive_interval sets the
|
|
155
|
+
keep_alive_interval sets the seconds of ping message
|
|
165
156
|
|
|
166
157
|
```python
|
|
167
158
|
hub_connection = HubConnectionBuilder()\
|
|
@@ -186,15 +177,32 @@ hub_connection = HubConnectionBuilder()\
|
|
|
186
177
|
"max_attempts": 5
|
|
187
178
|
}).build()
|
|
188
179
|
```
|
|
180
|
+
|
|
181
|
+
## Configure messagepack
|
|
182
|
+
|
|
183
|
+
```python
|
|
184
|
+
from signalrcore.protocol.messagepack_protocol import MessagePackHubProtocol
|
|
185
|
+
|
|
186
|
+
HubConnectionBuilder()\
|
|
187
|
+
.with_url(self.server_url, options={"verify_ssl":False})\
|
|
188
|
+
...
|
|
189
|
+
.with_hub_protocol(MessagePackHubProtocol())\
|
|
190
|
+
...
|
|
191
|
+
.build()
|
|
192
|
+
```
|
|
189
193
|
## Events
|
|
190
194
|
|
|
191
|
-
### On
|
|
192
|
-
on_open - fires when connection is
|
|
195
|
+
### On Connect / On Disconnect
|
|
196
|
+
on_open - fires when connection is opened and ready to send messages
|
|
193
197
|
on_close - fires when connection is closed
|
|
194
198
|
```python
|
|
195
199
|
hub_connection.on_open(lambda: print("connection opened and handshake received ready to send messages"))
|
|
196
200
|
hub_connection.on_close(lambda: print("connection closed"))
|
|
197
201
|
|
|
202
|
+
```
|
|
203
|
+
### On Hub Error (Hub Exceptions ...)
|
|
204
|
+
```
|
|
205
|
+
hub_connection.on_error(lambda data: print(f"An exception was thrown closed{data.error}"))
|
|
198
206
|
```
|
|
199
207
|
### Register an operation
|
|
200
208
|
ReceiveMessage - signalr method
|
|
@@ -208,6 +216,7 @@ username, message - parameters of signalrmethod
|
|
|
208
216
|
```python
|
|
209
217
|
hub_connection.send("SendMessage", [username, message])
|
|
210
218
|
```
|
|
219
|
+
|
|
211
220
|
## Sending messages with callback
|
|
212
221
|
SendMessage - signalr method
|
|
213
222
|
username, message - parameters of signalrmethod
|
|
@@ -221,6 +230,7 @@ username, message - parameters of signalrmethod
|
|
|
221
230
|
if not send_callback_received.acquire(timeout=1):
|
|
222
231
|
raise ValueError("CALLBACK NOT RECEIVED")
|
|
223
232
|
```
|
|
233
|
+
|
|
224
234
|
## Requesting streaming (Server to client)
|
|
225
235
|
```python
|
|
226
236
|
hub_connection.stream(
|
|
@@ -245,10 +255,6 @@ subject.next(str(iteration))
|
|
|
245
255
|
|
|
246
256
|
# End streaming
|
|
247
257
|
subject.complete()
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
258
|
```
|
|
253
259
|
|
|
254
260
|
# Full Examples
|
|
@@ -301,4 +307,4 @@ hub_connection.stop()
|
|
|
301
307
|
|
|
302
308
|
sys.exit(0)
|
|
303
309
|
|
|
304
|
-
```
|
|
310
|
+
```
|
|
File without changes
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import setuptools
|
|
2
|
+
|
|
3
|
+
with open("README.md", "r") as fh:
|
|
4
|
+
long_description = fh.read()
|
|
5
|
+
|
|
6
|
+
setuptools.setup(
|
|
7
|
+
name="signalrcore",
|
|
8
|
+
version="0.9.6b1",
|
|
9
|
+
author="mandrewcito",
|
|
10
|
+
author_email="signalrcore@mandrewcito.dev",
|
|
11
|
+
description="A Python SignalR Core client(json and messagepack),"
|
|
12
|
+
"with invocation auth and two way streaming."
|
|
13
|
+
"Compatible with azure / serverless functions."
|
|
14
|
+
"Also with automatic reconnect and manually reconnect.",
|
|
15
|
+
keywords="signalr core client 3.1",
|
|
16
|
+
long_description=long_description,
|
|
17
|
+
long_description_content_type="text/markdown",
|
|
18
|
+
license_file="LICENSE",
|
|
19
|
+
url="https://github.com/mandrewcito/signalrcore",
|
|
20
|
+
packages=setuptools.find_packages(),
|
|
21
|
+
classifiers=[
|
|
22
|
+
"Programming Language :: Python :: 3.8",
|
|
23
|
+
"License :: OSI Approved :: MIT License",
|
|
24
|
+
"Operating System :: OS Independent"
|
|
25
|
+
],
|
|
26
|
+
install_requires=[
|
|
27
|
+
"msgpack==1.0.2"
|
|
28
|
+
],
|
|
29
|
+
extras_require={
|
|
30
|
+
'dev': [
|
|
31
|
+
'requests',
|
|
32
|
+
'flake8',
|
|
33
|
+
'coverage',
|
|
34
|
+
'pytest',
|
|
35
|
+
'pytest-cov'
|
|
36
|
+
]
|
|
37
|
+
},
|
|
38
|
+
)
|
|
File without changes
|