dsmq 1.0.0__py3-none-any.whl → 1.2.0__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.
- dsmq/client.py +40 -2
- dsmq/{demo_linux.py → demo.py} +0 -3
- dsmq/server.py +58 -11
- dsmq/tests/__init__.py +0 -0
- dsmq/tests/integration_test.py +243 -0
- {dsmq-1.0.0.dist-info → dsmq-1.2.0.dist-info}/METADATA +30 -2
- dsmq-1.2.0.dist-info/RECORD +12 -0
- dsmq-1.0.0.dist-info/RECORD +0 -10
- {dsmq-1.0.0.dist-info → dsmq-1.2.0.dist-info}/WHEEL +0 -0
- {dsmq-1.0.0.dist-info → dsmq-1.2.0.dist-info}/licenses/LICENSE +0 -0
dsmq/client.py
CHANGED
@@ -1,9 +1,13 @@
|
|
1
1
|
import json
|
2
|
+
import time
|
2
3
|
from websockets.sync.client import connect as ws_connect
|
3
4
|
|
4
5
|
_default_host = "127.0.0.1"
|
5
6
|
_default_port = 30008
|
6
7
|
|
8
|
+
_n_retries = 10
|
9
|
+
_initial_retry = 0.01 # seconds
|
10
|
+
|
7
11
|
|
8
12
|
def connect(host=_default_host, port=_default_port):
|
9
13
|
return DSMQClientSideConnection(host, port)
|
@@ -12,16 +16,50 @@ def connect(host=_default_host, port=_default_port):
|
|
12
16
|
class DSMQClientSideConnection:
|
13
17
|
def __init__(self, host, port):
|
14
18
|
self.uri = f"ws://{host}:{port}"
|
15
|
-
|
19
|
+
print(f"Connecting to dsmq server at {self.uri}")
|
20
|
+
for i_retry in range(_n_retries):
|
21
|
+
try:
|
22
|
+
self.websocket = ws_connect(self.uri)
|
23
|
+
break
|
24
|
+
except ConnectionRefusedError:
|
25
|
+
self.websocket = None
|
26
|
+
# Exponential backoff
|
27
|
+
# Wait twice as long each time before trying again.
|
28
|
+
time.sleep(_initial_retry * 2**i_retry)
|
29
|
+
print(" ...trying again")
|
30
|
+
|
31
|
+
if self.websocket is None:
|
32
|
+
raise ConnectionRefusedError("Could not connect to dsmq server.")
|
33
|
+
|
34
|
+
self.time_of_last_request = time.time()
|
16
35
|
|
17
36
|
def get(self, topic):
|
18
37
|
msg = {"action": "get", "topic": topic}
|
19
38
|
self.websocket.send(json.dumps(msg))
|
20
|
-
|
21
39
|
msg_text = self.websocket.recv()
|
22
40
|
msg = json.loads(msg_text)
|
23
41
|
return msg["message"]
|
24
42
|
|
43
|
+
def get_wait(self, topic):
|
44
|
+
"""
|
45
|
+
A variant of `get()` that retries a few times until it gets
|
46
|
+
a non-empty message. Adjust `_n_tries` and `_initial_retry`
|
47
|
+
to change how persistent it will be.
|
48
|
+
"""
|
49
|
+
for i_retry in range(_n_retries):
|
50
|
+
message = self.get(topic)
|
51
|
+
if message != "":
|
52
|
+
return message
|
53
|
+
time.sleep(_initial_retry * 2**i_retry)
|
54
|
+
return message
|
55
|
+
|
25
56
|
def put(self, topic, msg_body):
|
26
57
|
msg_dict = {"action": "put", "topic": topic, "message": msg_body}
|
27
58
|
self.websocket.send(json.dumps(msg_dict))
|
59
|
+
|
60
|
+
def shutdown_server(self):
|
61
|
+
msg_dict = {"action": "shutdown", "topic": ""}
|
62
|
+
self.websocket.send(json.dumps(msg_dict))
|
63
|
+
|
64
|
+
def close(self):
|
65
|
+
self.websocket.close()
|
dsmq/{demo_linux.py → demo.py}
RENAMED
@@ -1,11 +1,8 @@
|
|
1
|
-
# Heads up: This script only works on Linux because of use of "fork" method.
|
2
1
|
import multiprocessing as mp
|
3
2
|
from dsmq.server import serve
|
4
3
|
import dsmq.example_get_client
|
5
4
|
import dsmq.example_put_client
|
6
5
|
|
7
|
-
mp.set_start_method("fork")
|
8
|
-
|
9
6
|
HOST = "127.0.0.1"
|
10
7
|
PORT = 25252
|
11
8
|
|
dsmq/server.py
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
import json
|
2
|
+
import os
|
2
3
|
import sqlite3
|
3
4
|
import sys
|
5
|
+
from threading import Thread
|
4
6
|
import time
|
5
7
|
from websockets.sync.server import serve as ws_serve
|
6
8
|
|
@@ -8,30 +10,58 @@ _default_host = "127.0.0.1"
|
|
8
10
|
_default_port = 30008
|
9
11
|
_n_retries = 5
|
10
12
|
_first_retry = 0.01 # seconds
|
13
|
+
_pause = 0.01 # seconds
|
11
14
|
_time_to_live = 600.0 # seconds
|
12
15
|
|
16
|
+
_db_name = "file::memory:?cache=shared"
|
17
|
+
|
18
|
+
# Make this global so it's easy to share
|
19
|
+
dsmq_server = None
|
20
|
+
|
13
21
|
|
14
22
|
def serve(host=_default_host, port=_default_port):
|
15
23
|
"""
|
16
24
|
For best results, start this running in its own process and walk away.
|
17
25
|
"""
|
18
|
-
|
26
|
+
# Cleanup temp files.
|
27
|
+
# Under some condition
|
28
|
+
# (which I haven't yet been able to pin down)
|
29
|
+
# a file is generated with the db name.
|
30
|
+
# If it is not removed, it gets
|
31
|
+
# treated as a SQLite db on disk,
|
32
|
+
# which dramatically slows it down,
|
33
|
+
# especially the way it's used here for
|
34
|
+
# rapid-fire one-item reads and writes.
|
35
|
+
filenames = os.listdir()
|
36
|
+
for filename in filenames:
|
37
|
+
if filename[: len(_db_name)] == _db_name:
|
38
|
+
os.remove(filename)
|
39
|
+
|
40
|
+
sqlite_conn = sqlite3.connect(_db_name)
|
19
41
|
cursor = sqlite_conn.cursor()
|
20
42
|
cursor.execute("""
|
21
43
|
CREATE TABLE IF NOT EXISTS messages (timestamp DOUBLE, topic TEXT, message TEXT)
|
22
44
|
""")
|
23
45
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
46
|
+
# Making this global in scope is a way to make it available
|
47
|
+
# to the shutdown operation. It's an awkward construction,
|
48
|
+
# and a method of last resort. (If you stumble across this and
|
49
|
+
# figure out something more elegant, please submit a PR!
|
50
|
+
# or send it to me at brohrer@gmail.com,
|
51
|
+
global dsmq_server
|
52
|
+
|
53
|
+
# dsmq_server = ws_serve(request_handler, host, port)
|
54
|
+
with ws_serve(request_handler, host, port) as dsmq_server:
|
55
|
+
dsmq_server.serve_forever()
|
56
|
+
print()
|
57
|
+
print(f"Server started at {host} on port {port}.")
|
58
|
+
print("Waiting for clients...")
|
29
59
|
|
30
60
|
sqlite_conn.close()
|
31
61
|
|
32
62
|
|
33
63
|
def request_handler(websocket):
|
34
|
-
sqlite_conn = sqlite3.connect(
|
64
|
+
sqlite_conn = sqlite3.connect(_db_name)
|
35
65
|
cursor = sqlite_conn.cursor()
|
36
66
|
|
37
67
|
client_creation_time = time.time()
|
@@ -85,7 +115,7 @@ FROM messages,
|
|
85
115
|
SELECT MIN(timestamp) AS min_time
|
86
116
|
FROM messages
|
87
117
|
WHERE topic = :topic
|
88
|
-
|
118
|
+
AND timestamp > :last_read_time
|
89
119
|
) a
|
90
120
|
WHERE topic = :topic
|
91
121
|
AND timestamp = a.min_time
|
@@ -108,9 +138,26 @@ AND timestamp = a.min_time
|
|
108
138
|
message = ""
|
109
139
|
|
110
140
|
websocket.send(json.dumps({"message": message}))
|
141
|
+
elif msg["action"] == "shutdown":
|
142
|
+
# Run this from a separate thread to prevent deadlock
|
143
|
+
global dsmq_server
|
144
|
+
print("Shutting down the dsmq server.")
|
145
|
+
|
146
|
+
def shutdown_gracefully(server_to_shutdown):
|
147
|
+
server_to_shutdown.shutdown()
|
148
|
+
|
149
|
+
filenames = os.listdir()
|
150
|
+
for filename in filenames:
|
151
|
+
if filename[: len(_db_name)] == _db_name:
|
152
|
+
try:
|
153
|
+
os.remove(filename)
|
154
|
+
except FileNotFoundError:
|
155
|
+
pass
|
156
|
+
|
157
|
+
Thread(target=shutdown_gracefully, args=(dsmq_server,)).start()
|
158
|
+
break
|
111
159
|
else:
|
112
|
-
print("Action must either be 'put' or '
|
113
|
-
|
160
|
+
print("Action must either be 'put', 'get', or 'shudown'")
|
114
161
|
|
115
162
|
# Periodically clean out messages from the queue that are
|
116
163
|
# past their sell buy date.
|
@@ -121,7 +168,7 @@ AND timestamp = a.min_time
|
|
121
168
|
DELETE FROM messages
|
122
169
|
WHERE timestamp < :time_threshold
|
123
170
|
""",
|
124
|
-
{"time_threshold": time_of_last_purge}
|
171
|
+
{"time_threshold": time_of_last_purge},
|
125
172
|
)
|
126
173
|
sqlite_conn.commit()
|
127
174
|
time_of_last_purge = time.time()
|
dsmq/tests/__init__.py
ADDED
File without changes
|
@@ -0,0 +1,243 @@
|
|
1
|
+
import multiprocessing as mp
|
2
|
+
import time
|
3
|
+
from websockets.exceptions import ConnectionClosed
|
4
|
+
from dsmq.server import serve
|
5
|
+
from dsmq.client import connect
|
6
|
+
|
7
|
+
# spawn is the default method on macOS
|
8
|
+
# mp.set_start_method('spawn')
|
9
|
+
|
10
|
+
host = "127.0.0.1"
|
11
|
+
port = 30303
|
12
|
+
|
13
|
+
_short_pause = 0.001
|
14
|
+
_pause = 0.01
|
15
|
+
_long_pause = 0.1
|
16
|
+
_very_long_pause = 2.0
|
17
|
+
|
18
|
+
|
19
|
+
def test_client_server():
|
20
|
+
p_server = mp.Process(target=serve, args=(host, port))
|
21
|
+
p_server.start()
|
22
|
+
mq = connect(host, port)
|
23
|
+
read_completes = False
|
24
|
+
write_completes = False
|
25
|
+
|
26
|
+
n_iter = 11
|
27
|
+
for i in range(n_iter):
|
28
|
+
mq.put("test", f"msg_{i}")
|
29
|
+
write_completes = True
|
30
|
+
|
31
|
+
for i in range(n_iter):
|
32
|
+
msg = mq.get("test")
|
33
|
+
read_completes = True
|
34
|
+
|
35
|
+
assert msg
|
36
|
+
assert write_completes
|
37
|
+
assert read_completes
|
38
|
+
|
39
|
+
mq.shutdown_server()
|
40
|
+
mq.close()
|
41
|
+
|
42
|
+
closed = False
|
43
|
+
try:
|
44
|
+
mq = connect(host, port)
|
45
|
+
except ConnectionRefusedError as e:
|
46
|
+
print(e)
|
47
|
+
closed = True
|
48
|
+
assert closed
|
49
|
+
|
50
|
+
|
51
|
+
def test_write_one_read_one():
|
52
|
+
p_server = mp.Process(target=serve, args=(host, port))
|
53
|
+
p_server.start()
|
54
|
+
write_client = connect(host, port)
|
55
|
+
read_client = connect(host, port)
|
56
|
+
|
57
|
+
write_client.put("test", "test_msg")
|
58
|
+
|
59
|
+
# It takes a moment for the write to complete
|
60
|
+
time.sleep(_pause)
|
61
|
+
msg = read_client.get("test")
|
62
|
+
|
63
|
+
assert msg == "test_msg"
|
64
|
+
|
65
|
+
write_client.shutdown_server()
|
66
|
+
write_client.close()
|
67
|
+
read_client.close()
|
68
|
+
|
69
|
+
|
70
|
+
def test_get_wait():
|
71
|
+
p_server = mp.Process(target=serve, args=(host, port))
|
72
|
+
p_server.start()
|
73
|
+
write_client = connect(host, port)
|
74
|
+
read_client = connect(host, port)
|
75
|
+
|
76
|
+
write_client.put("test", "test_msg")
|
77
|
+
|
78
|
+
msg = read_client.get_wait("test")
|
79
|
+
|
80
|
+
assert msg == "test_msg"
|
81
|
+
|
82
|
+
write_client.shutdown_server()
|
83
|
+
write_client.close()
|
84
|
+
read_client.close()
|
85
|
+
|
86
|
+
|
87
|
+
def test_multitopics():
|
88
|
+
p_server = mp.Process(target=serve, args=(host, port))
|
89
|
+
p_server.start()
|
90
|
+
write_client = connect(host, port)
|
91
|
+
read_client = connect(host, port)
|
92
|
+
|
93
|
+
write_client.put("test_A", "test_msg_A")
|
94
|
+
write_client.put("test_B", "test_msg_B")
|
95
|
+
|
96
|
+
msg_A = read_client.get_wait("test_A")
|
97
|
+
msg_B = read_client.get_wait("test_B")
|
98
|
+
|
99
|
+
assert msg_A == "test_msg_A"
|
100
|
+
assert msg_B == "test_msg_B"
|
101
|
+
|
102
|
+
write_client.shutdown_server()
|
103
|
+
write_client.close()
|
104
|
+
read_client.close()
|
105
|
+
|
106
|
+
|
107
|
+
def test_client_history_cutoff():
|
108
|
+
p_server = mp.Process(target=serve, args=(host, port))
|
109
|
+
p_server.start()
|
110
|
+
write_client = connect(host, port)
|
111
|
+
write_client.put("test", "test_msg")
|
112
|
+
time.sleep(_pause)
|
113
|
+
|
114
|
+
read_client = connect(host, port)
|
115
|
+
msg = read_client.get("test")
|
116
|
+
|
117
|
+
assert msg == ""
|
118
|
+
|
119
|
+
write_client.shutdown_server()
|
120
|
+
write_client.close()
|
121
|
+
read_client.close()
|
122
|
+
|
123
|
+
|
124
|
+
def test_two_write_clients():
|
125
|
+
p_server = mp.Process(target=serve, args=(host, port))
|
126
|
+
p_server.start()
|
127
|
+
write_client_A = connect(host, port)
|
128
|
+
write_client_B = connect(host, port)
|
129
|
+
read_client = connect(host, port)
|
130
|
+
|
131
|
+
write_client_A.put("test", "test_msg_A")
|
132
|
+
# Wait briefly, to ensure the order of writes
|
133
|
+
time.sleep(_pause)
|
134
|
+
write_client_B.put("test", "test_msg_B")
|
135
|
+
msg_A = read_client.get_wait("test")
|
136
|
+
msg_B = read_client.get_wait("test")
|
137
|
+
|
138
|
+
assert msg_A == "test_msg_A"
|
139
|
+
assert msg_B == "test_msg_B"
|
140
|
+
|
141
|
+
write_client_A.shutdown_server()
|
142
|
+
write_client_A.close()
|
143
|
+
write_client_B.close()
|
144
|
+
read_client.close()
|
145
|
+
|
146
|
+
|
147
|
+
def test_two_read_clients():
|
148
|
+
p_server = mp.Process(target=serve, args=(host, port))
|
149
|
+
p_server.start()
|
150
|
+
write_client = connect(host, port)
|
151
|
+
read_client_A = connect(host, port)
|
152
|
+
read_client_B = connect(host, port)
|
153
|
+
|
154
|
+
write_client.put("test", "test_msg")
|
155
|
+
msg_A = read_client_A.get_wait("test")
|
156
|
+
msg_B = read_client_B.get_wait("test")
|
157
|
+
|
158
|
+
assert msg_A == "test_msg"
|
159
|
+
assert msg_B == "test_msg"
|
160
|
+
|
161
|
+
write_client.shutdown_server()
|
162
|
+
write_client.close()
|
163
|
+
read_client_A.close()
|
164
|
+
read_client_B.close()
|
165
|
+
|
166
|
+
|
167
|
+
def speed_write(stop_flag):
|
168
|
+
fast_write_client = connect(host, port)
|
169
|
+
while True:
|
170
|
+
fast_write_client.put("speed_test", "speed")
|
171
|
+
if stop_flag.is_set():
|
172
|
+
break
|
173
|
+
fast_write_client.close()
|
174
|
+
|
175
|
+
|
176
|
+
def test_speed_writing():
|
177
|
+
p_server = mp.Process(target=serve, args=(host, port))
|
178
|
+
p_server.start()
|
179
|
+
write_client = connect(host, port)
|
180
|
+
read_client = connect(host, port)
|
181
|
+
|
182
|
+
stop_flag = mp.Event()
|
183
|
+
p_speed_write = mp.Process(target=speed_write, args=(stop_flag,))
|
184
|
+
p_speed_write.start()
|
185
|
+
time.sleep(_pause)
|
186
|
+
|
187
|
+
# time_a = time.time()
|
188
|
+
write_client.put("test", "test_msg")
|
189
|
+
# time_b = time.time()
|
190
|
+
msg = read_client.get_wait("test")
|
191
|
+
# time_c = time.time()
|
192
|
+
|
193
|
+
# write_time = int((time_b - time_a) * 1e6)
|
194
|
+
# read_time = int((time_c - time_b) * 1e6)
|
195
|
+
# print(f"write time: {write_time} us, read time: {read_time} us")
|
196
|
+
|
197
|
+
assert msg == "test_msg"
|
198
|
+
|
199
|
+
stop_flag.set()
|
200
|
+
p_speed_write.join()
|
201
|
+
read_client.close()
|
202
|
+
write_client.shutdown_server()
|
203
|
+
write_client.close()
|
204
|
+
|
205
|
+
|
206
|
+
def speed_read(stop_flag):
|
207
|
+
fast_read_client = connect(host, port)
|
208
|
+
while True:
|
209
|
+
fast_read_client.get("speed_test")
|
210
|
+
if stop_flag.is_set():
|
211
|
+
break
|
212
|
+
fast_read_client.close()
|
213
|
+
|
214
|
+
|
215
|
+
def test_speed_reading():
|
216
|
+
p_server = mp.Process(target=serve, args=(host, port))
|
217
|
+
p_server.start()
|
218
|
+
write_client = connect(host, port)
|
219
|
+
read_client = connect(host, port)
|
220
|
+
|
221
|
+
stop_flag = mp.Event()
|
222
|
+
p_speed_read = mp.Process(target=speed_read, args=(stop_flag,))
|
223
|
+
p_speed_read.start()
|
224
|
+
|
225
|
+
# time_a = time.time()
|
226
|
+
write_client.put("test", "test_msg")
|
227
|
+
# time_b = time.time()
|
228
|
+
msg = read_client.get_wait("test")
|
229
|
+
# time_c = time.time()
|
230
|
+
|
231
|
+
# write_time = int((time_b - time_a) * 1e6)
|
232
|
+
# read_time = int((time_c - time_b) * 1e6)
|
233
|
+
# print(f"write time: {write_time} us, read time: {read_time} us")
|
234
|
+
|
235
|
+
assert msg == "test_msg"
|
236
|
+
|
237
|
+
stop_flag.set()
|
238
|
+
p_speed_read.join()
|
239
|
+
p_speed_read.kill()
|
240
|
+
read_client.close()
|
241
|
+
write_client.shutdown_server()
|
242
|
+
# time.sleep(_pause)
|
243
|
+
write_client.close()
|
@@ -1,9 +1,10 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: dsmq
|
3
|
-
Version: 1.
|
3
|
+
Version: 1.2.0
|
4
4
|
Summary: A dead simple message queue
|
5
5
|
License-File: LICENSE
|
6
6
|
Requires-Python: >=3.10
|
7
|
+
Requires-Dist: pytest>=8.3.4
|
7
8
|
Requires-Dist: websockets>=14.1
|
8
9
|
Description-Content-Type: text/markdown
|
9
10
|
|
@@ -86,7 +87,7 @@ p_mq.close()
|
|
86
87
|
1. In the second, run `src/dsmq/example_put_client.py`.
|
87
88
|
1. In the third, run `src/dsmq/example_get_client.py`.
|
88
89
|
|
89
|
-
Alternatively,
|
90
|
+
Alternatively, you can run them all at once with `src/dsmq/demo.py`.
|
90
91
|
|
91
92
|
## How it works
|
92
93
|
|
@@ -150,3 +151,30 @@ connected to the server.
|
|
150
151
|
- returns str, the content of the message. If there was no eligble message
|
151
152
|
in the topic, or the topic doesn't yet exist,
|
152
153
|
returns `""`.
|
154
|
+
|
155
|
+
### `get_wait(topic)`
|
156
|
+
|
157
|
+
A variant of `get()` that retries a few times until it gets
|
158
|
+
a non-empty message. Adjust internal values `_n_tries` and `_initial_retry`
|
159
|
+
to change how persistent it will be.
|
160
|
+
|
161
|
+
- `topic` (str)
|
162
|
+
- returns str, the content of the message. If there was no eligble message
|
163
|
+
in the topic after the allotted number of tries,
|
164
|
+
or the topic doesn't yet exist,
|
165
|
+
returns `""`.
|
166
|
+
|
167
|
+
### `shutdown_server()`
|
168
|
+
|
169
|
+
Gracefully shut down the server, through the client connection.
|
170
|
+
|
171
|
+
### `close()`
|
172
|
+
|
173
|
+
Gracefully shut down the client connection.
|
174
|
+
|
175
|
+
# Testing
|
176
|
+
|
177
|
+
Run all the tests in `src/dsmq/tests/` with pytest, for example
|
178
|
+
```
|
179
|
+
uv run pytest
|
180
|
+
```
|
@@ -0,0 +1,12 @@
|
|
1
|
+
dsmq/__init__.py,sha256=YCgbnQAk8YbtHRyMcU0v2O7RdRhPhlT-vS_q40a7Q6g,50
|
2
|
+
dsmq/client.py,sha256=2i3BhpQM71j-uZlqiJvzQgywi1y07K1VgQe8i2Koi0g,2070
|
3
|
+
dsmq/demo.py,sha256=K53cC5kN7K4kNJlPq7c5OTIMHRCKTo9hYX2aIos57rU,542
|
4
|
+
dsmq/example_get_client.py,sha256=PvAsDGEAH1kVBifLVg2rx8ZxnAZmvzVCvZq13VgpLds,301
|
5
|
+
dsmq/example_put_client.py,sha256=QxDc3i7KAjjhpwxRRpI0Ke5KTNSPuBf9kkcGyTvUEaw,353
|
6
|
+
dsmq/server.py,sha256=BlCG8soixdYmL4OV0-yVU-8kpg9c9OfkzZi5x97wDu0,6030
|
7
|
+
dsmq/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
8
|
+
dsmq/tests/integration_test.py,sha256=lC97LAzdQixv75OwjqjKTvYnSZpsP0zuzFP8ocUnjl8,6031
|
9
|
+
dsmq-1.2.0.dist-info/METADATA,sha256=Y-uwBET49Bk_ma2sYGDP7JBuLfnNvx2_3mJN1i2Bmiw,4730
|
10
|
+
dsmq-1.2.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
11
|
+
dsmq-1.2.0.dist-info/licenses/LICENSE,sha256=3Yu1mAp5VsKmnDtzkiOY7BdmrLeNwwZ3t6iWaLnlL0Y,1071
|
12
|
+
dsmq-1.2.0.dist-info/RECORD,,
|
dsmq-1.0.0.dist-info/RECORD
DELETED
@@ -1,10 +0,0 @@
|
|
1
|
-
dsmq/__init__.py,sha256=YCgbnQAk8YbtHRyMcU0v2O7RdRhPhlT-vS_q40a7Q6g,50
|
2
|
-
dsmq/client.py,sha256=sgkz7iabc8hirq0HRfhqlKCPwHVYgvg2C01aoRbvTSo,768
|
3
|
-
dsmq/demo_linux.py,sha256=O5B2DH9pAvCCaYSRE5DV1o2fSx_bXU9hcxTis0ier5I,648
|
4
|
-
dsmq/example_get_client.py,sha256=PvAsDGEAH1kVBifLVg2rx8ZxnAZmvzVCvZq13VgpLds,301
|
5
|
-
dsmq/example_put_client.py,sha256=QxDc3i7KAjjhpwxRRpI0Ke5KTNSPuBf9kkcGyTvUEaw,353
|
6
|
-
dsmq/server.py,sha256=fFM8soN4y8CULX5yk3Temir-pl2K1hp38MOEwqzPN5U,4343
|
7
|
-
dsmq-1.0.0.dist-info/METADATA,sha256=TaoyVGkRJasSK-D6UQ9vNTeY07gOH9At7j1rZgiFxp0,4069
|
8
|
-
dsmq-1.0.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
9
|
-
dsmq-1.0.0.dist-info/licenses/LICENSE,sha256=3Yu1mAp5VsKmnDtzkiOY7BdmrLeNwwZ3t6iWaLnlL0Y,1071
|
10
|
-
dsmq-1.0.0.dist-info/RECORD,,
|
File without changes
|
File without changes
|