runtimepy 5.4.2__py3-none-any.whl → 5.4.4__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.
- runtimepy/__init__.py +2 -2
- runtimepy/commands/tftp.py +3 -4
- runtimepy/data/css/bootstrap_extra.css +4 -0
- runtimepy/net/server/app/env/tab/html.py +4 -2
- runtimepy/net/udp/tftp/__init__.py +14 -0
- runtimepy/net/udp/tftp/base.py +12 -5
- {runtimepy-5.4.2.dist-info → runtimepy-5.4.4.dist-info}/METADATA +5 -5
- {runtimepy-5.4.2.dist-info → runtimepy-5.4.4.dist-info}/RECORD +12 -12
- {runtimepy-5.4.2.dist-info → runtimepy-5.4.4.dist-info}/WHEEL +1 -1
- {runtimepy-5.4.2.dist-info → runtimepy-5.4.4.dist-info}/LICENSE +0 -0
- {runtimepy-5.4.2.dist-info → runtimepy-5.4.4.dist-info}/entry_points.txt +0 -0
- {runtimepy-5.4.2.dist-info → runtimepy-5.4.4.dist-info}/top_level.txt +0 -0
runtimepy/__init__.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# =====================================
|
|
2
2
|
# generator=datazen
|
|
3
3
|
# version=3.1.4
|
|
4
|
-
# hash=
|
|
4
|
+
# hash=5a37b52aedb2af82fb174fbea8ce0c1f
|
|
5
5
|
# =====================================
|
|
6
6
|
|
|
7
7
|
"""
|
|
@@ -10,7 +10,7 @@ Useful defaults and other package metadata.
|
|
|
10
10
|
|
|
11
11
|
DESCRIPTION = "A framework for implementing Python services."
|
|
12
12
|
PKG_NAME = "runtimepy"
|
|
13
|
-
VERSION = "5.4.
|
|
13
|
+
VERSION = "5.4.4"
|
|
14
14
|
|
|
15
15
|
# runtimepy-specific content.
|
|
16
16
|
METRICS_NAME = "metrics"
|
runtimepy/commands/tftp.py
CHANGED
|
@@ -8,13 +8,12 @@ import asyncio
|
|
|
8
8
|
from pathlib import Path
|
|
9
9
|
from socket import getaddrinfo
|
|
10
10
|
|
|
11
|
-
from vcorelib.args import CommandFunction
|
|
12
|
-
|
|
13
11
|
# third-party
|
|
12
|
+
from vcorelib.args import CommandFunction
|
|
14
13
|
from vcorelib.asyncio import run_handle_stop
|
|
15
14
|
|
|
16
15
|
# internal
|
|
17
|
-
from runtimepy.net.udp.tftp import tftp_read, tftp_write
|
|
16
|
+
from runtimepy.net.udp.tftp import TFTP_PORT, tftp_read, tftp_write
|
|
18
17
|
from runtimepy.net.udp.tftp.base import DEFAULT_TIMEOUT_S, REEMIT_PERIOD_S
|
|
19
18
|
from runtimepy.net.udp.tftp.enums import DEFAULT_MODE
|
|
20
19
|
|
|
@@ -53,7 +52,7 @@ def add_tftp_cmd(parser: argparse.ArgumentParser) -> CommandFunction:
|
|
|
53
52
|
"-p",
|
|
54
53
|
"--port",
|
|
55
54
|
type=int,
|
|
56
|
-
default=
|
|
55
|
+
default=TFTP_PORT,
|
|
57
56
|
help="port to message (default: %(default)s)",
|
|
58
57
|
)
|
|
59
58
|
|
|
@@ -134,7 +134,9 @@ class ChannelEnvironmentTabHtml(ChannelEnvironmentTabControls):
|
|
|
134
134
|
def channel_table(self, parent: Element) -> None:
|
|
135
135
|
"""Create the channel table."""
|
|
136
136
|
|
|
137
|
-
table = div(
|
|
137
|
+
table = div(
|
|
138
|
+
tag="table", parent=div(parent=parent, class_str="table-container")
|
|
139
|
+
)
|
|
138
140
|
table.add_class("table", TEXT)
|
|
139
141
|
|
|
140
142
|
header = div(tag="thead", parent=table)
|
|
@@ -248,7 +250,7 @@ class ChannelEnvironmentTabHtml(ChannelEnvironmentTabControls):
|
|
|
248
250
|
# table doesn't take up full vertical space, few channels).
|
|
249
251
|
under_construction(
|
|
250
252
|
vert_container,
|
|
251
|
-
class_str="border-start border-end",
|
|
253
|
+
class_str="border-start border-top border-end",
|
|
252
254
|
note="unused space",
|
|
253
255
|
)
|
|
254
256
|
|
|
@@ -21,6 +21,7 @@ from runtimepy.net.udp.tftp.base import (
|
|
|
21
21
|
DEFAULT_TIMEOUT_S,
|
|
22
22
|
REEMIT_PERIOD_S,
|
|
23
23
|
BaseTftpConnection,
|
|
24
|
+
TftpErrorHandler,
|
|
24
25
|
)
|
|
25
26
|
from runtimepy.net.udp.tftp.enums import DEFAULT_MODE
|
|
26
27
|
from runtimepy.util import PossiblePath, as_path
|
|
@@ -194,6 +195,9 @@ class TftpConnection(BaseTftpConnection):
|
|
|
194
195
|
return result
|
|
195
196
|
|
|
196
197
|
|
|
198
|
+
TFTP_PORT = 69
|
|
199
|
+
|
|
200
|
+
|
|
197
201
|
@asynccontextmanager
|
|
198
202
|
async def tftp(
|
|
199
203
|
addr: Union[IpHost, tuple[str, int]],
|
|
@@ -201,6 +205,7 @@ async def tftp(
|
|
|
201
205
|
connection_kwargs: dict[str, Any] = None,
|
|
202
206
|
timeout_s: float = DEFAULT_TIMEOUT_S,
|
|
203
207
|
reemit_period_s: float = REEMIT_PERIOD_S,
|
|
208
|
+
error_handler: TftpErrorHandler = None,
|
|
204
209
|
) -> AsyncIterator[TftpConnection]:
|
|
205
210
|
"""Use a tftp connection as a managed context."""
|
|
206
211
|
|
|
@@ -215,6 +220,11 @@ async def tftp(
|
|
|
215
220
|
conn = await TftpConnection.create_connection(
|
|
216
221
|
remote_addr=(addr.name, addr.port), **connection_kwargs
|
|
217
222
|
)
|
|
223
|
+
|
|
224
|
+
# Add error handlers.
|
|
225
|
+
if error_handler is not None:
|
|
226
|
+
conn.error_handlers.append(error_handler)
|
|
227
|
+
|
|
218
228
|
async with conn.process_then_disable(**process_kwargs):
|
|
219
229
|
# Set parameters.
|
|
220
230
|
conn.endpoint_timeout.value = timeout_s
|
|
@@ -232,6 +242,7 @@ async def tftp_write(
|
|
|
232
242
|
connection_kwargs: dict[str, Any] = None,
|
|
233
243
|
timeout_s: float = DEFAULT_TIMEOUT_S,
|
|
234
244
|
reemit_period_s: float = REEMIT_PERIOD_S,
|
|
245
|
+
error_handler: TftpErrorHandler = None,
|
|
235
246
|
) -> bool:
|
|
236
247
|
"""Attempt to perform a tftp write."""
|
|
237
248
|
|
|
@@ -241,6 +252,7 @@ async def tftp_write(
|
|
|
241
252
|
connection_kwargs=connection_kwargs,
|
|
242
253
|
timeout_s=timeout_s,
|
|
243
254
|
reemit_period_s=reemit_period_s,
|
|
255
|
+
error_handler=error_handler,
|
|
244
256
|
) as conn:
|
|
245
257
|
# Perform tftp interaction.
|
|
246
258
|
result = await conn.request_write(
|
|
@@ -259,6 +271,7 @@ async def tftp_read(
|
|
|
259
271
|
connection_kwargs: dict[str, Any] = None,
|
|
260
272
|
timeout_s: float = DEFAULT_TIMEOUT_S,
|
|
261
273
|
reemit_period_s: float = REEMIT_PERIOD_S,
|
|
274
|
+
error_handler: TftpErrorHandler = None,
|
|
262
275
|
) -> bool:
|
|
263
276
|
"""Attempt to perform a tftp read."""
|
|
264
277
|
|
|
@@ -268,6 +281,7 @@ async def tftp_read(
|
|
|
268
281
|
connection_kwargs=connection_kwargs,
|
|
269
282
|
timeout_s=timeout_s,
|
|
270
283
|
reemit_period_s=reemit_period_s,
|
|
284
|
+
error_handler=error_handler,
|
|
271
285
|
) as conn:
|
|
272
286
|
result = await conn.request_read(
|
|
273
287
|
destination, filename, mode=mode, addr=addr
|
runtimepy/net/udp/tftp/base.py
CHANGED
|
@@ -8,7 +8,7 @@ from contextlib import AsyncExitStack
|
|
|
8
8
|
from io import BytesIO
|
|
9
9
|
import logging
|
|
10
10
|
from pathlib import Path
|
|
11
|
-
from typing import BinaryIO, Union
|
|
11
|
+
from typing import BinaryIO, Callable, Union
|
|
12
12
|
|
|
13
13
|
# third-party
|
|
14
14
|
from vcorelib.math import metrics_time_ns
|
|
@@ -30,6 +30,8 @@ from runtimepy.primitives import Double, Uint16
|
|
|
30
30
|
REEMIT_PERIOD_S = 0.20
|
|
31
31
|
DEFAULT_TIMEOUT_S = 1.0
|
|
32
32
|
|
|
33
|
+
TftpErrorHandler = Callable[[TftpErrorCode, str, tuple[str, int]], None]
|
|
34
|
+
|
|
33
35
|
|
|
34
36
|
class BaseTftpConnection(UdpConnection):
|
|
35
37
|
"""A class implementing a basic tftp interface."""
|
|
@@ -73,6 +75,7 @@ class BaseTftpConnection(UdpConnection):
|
|
|
73
75
|
|
|
74
76
|
self.error_code = Uint16(time_source=metrics_time_ns)
|
|
75
77
|
self.env.channel("error_code", self.error_code, enum="TftpErrorCode")
|
|
78
|
+
self.error_handlers: list[TftpErrorHandler] = []
|
|
76
79
|
|
|
77
80
|
self.endpoint_period = Double(value=REEMIT_PERIOD_S)
|
|
78
81
|
self.env.channel(
|
|
@@ -346,10 +349,14 @@ class BaseTftpConnection(UdpConnection):
|
|
|
346
349
|
"""Handle an error message."""
|
|
347
350
|
|
|
348
351
|
# Update underlying primitive.
|
|
349
|
-
error_code = self.error_code.from_stream(stream)
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
352
|
+
error_code = TftpErrorCode(self.error_code.from_stream(stream))
|
|
353
|
+
message = stream.read().decode()
|
|
354
|
+
|
|
355
|
+
# Call extra error handlers.
|
|
356
|
+
for handler in self.error_handlers:
|
|
357
|
+
handler(error_code, message, addr)
|
|
358
|
+
|
|
359
|
+
self.endpoint(addr).handle_error(error_code, message)
|
|
353
360
|
|
|
354
361
|
async def process_datagram(
|
|
355
362
|
self, data: bytes, addr: tuple[str, int]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: runtimepy
|
|
3
|
-
Version: 5.4.
|
|
3
|
+
Version: 5.4.4
|
|
4
4
|
Summary: A framework for implementing Python services.
|
|
5
5
|
Home-page: https://github.com/vkottler/runtimepy
|
|
6
6
|
Author: Vaughn Kottler
|
|
@@ -17,9 +17,9 @@ Classifier: License :: OSI Approved :: MIT License
|
|
|
17
17
|
Requires-Python: >=3.11
|
|
18
18
|
Description-Content-Type: text/markdown
|
|
19
19
|
License-File: LICENSE
|
|
20
|
-
Requires-Dist: svgen >=0.6.8
|
|
21
|
-
Requires-Dist: vcorelib >=3.3.1
|
|
22
20
|
Requires-Dist: websockets
|
|
21
|
+
Requires-Dist: vcorelib >=3.3.1
|
|
22
|
+
Requires-Dist: svgen >=0.6.8
|
|
23
23
|
Requires-Dist: psutil
|
|
24
24
|
Provides-Extra: test
|
|
25
25
|
Requires-Dist: pylint ; extra == 'test'
|
|
@@ -44,11 +44,11 @@ Requires-Dist: uvloop ; (sys_platform != "win32" and sys_platform != "cygwin") a
|
|
|
44
44
|
=====================================
|
|
45
45
|
generator=datazen
|
|
46
46
|
version=3.1.4
|
|
47
|
-
hash=
|
|
47
|
+
hash=dbac0e58214ea7e4abbe7161a3c64749
|
|
48
48
|
=====================================
|
|
49
49
|
-->
|
|
50
50
|
|
|
51
|
-
# runtimepy ([5.4.
|
|
51
|
+
# runtimepy ([5.4.4](https://pypi.org/project/runtimepy/))
|
|
52
52
|
|
|
53
53
|
[](https://pypi.org/project/runtimepy/)
|
|
54
54
|

|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
runtimepy/__init__.py,sha256=
|
|
1
|
+
runtimepy/__init__.py,sha256=baR2RhS2-y7ZXgCnsPoi2qZNQvYUTMTNIsSR2qKnRNg,390
|
|
2
2
|
runtimepy/__main__.py,sha256=OPAed6hggoQdw-6QAR62mqLC-rCkdDhOq0wyeS2vDRI,332
|
|
3
3
|
runtimepy/app.py,sha256=sTvatbsGZ2Hdel36Si_WUbNMtg9CzsJyExr5xjIcxDE,970
|
|
4
4
|
runtimepy/dev_requirements.txt,sha256=j0dh11ztJAzfaUL0iFheGjaZj9ppDzmTkclTT8YKO8c,230
|
|
@@ -34,7 +34,7 @@ runtimepy/commands/arbiter.py,sha256=CtTMRYpqCAN3vWHkkr9jqWpoF7JGNXafKIBFmkarAfc
|
|
|
34
34
|
runtimepy/commands/common.py,sha256=NvZdeIFBHAF52c1n7vqD59DW6ywc-rG5iC5MpuhGf-c,2449
|
|
35
35
|
runtimepy/commands/server.py,sha256=T5IwBeqwJPpg35Ms_Vmz6xS1T-8U3fcgiRU6mAFlkEU,3767
|
|
36
36
|
runtimepy/commands/task.py,sha256=6xRVlRwpEZVhrcY18sQcfdWEOxeQZLeOF-6UrUURtO4,1435
|
|
37
|
-
runtimepy/commands/tftp.py,sha256=
|
|
37
|
+
runtimepy/commands/tftp.py,sha256=97Ev0bg0zI9WL_-BYWAyKWe3mC9xKsZ-gL1637ExdvE,2325
|
|
38
38
|
runtimepy/commands/tui.py,sha256=9hWA3_YATibUUDTVQr7UnKzPTDVJ7WxWKTYYQpLoyrE,1869
|
|
39
39
|
runtimepy/control/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
40
40
|
runtimepy/control/source.py,sha256=nW3Q2D-LcekII7K5XKbxXCcR-9jYQyvv0UypeNy1Dnw,1695
|
|
@@ -48,7 +48,7 @@ runtimepy/data/server.yaml,sha256=wS_Ceiu2TpkfPurpqoYoPlgzc9DAWtUd24MW7t-S5rU,97
|
|
|
48
48
|
runtimepy/data/server_base.yaml,sha256=QkF1xcHyMEViUhOc5rKFbFXjbRDDDHbX5LXvSQJRS58,615
|
|
49
49
|
runtimepy/data/server_dev.yaml,sha256=nQsPh7LuQig3pzHfdg_aD3yOUiCj1sKKfI-WwW3hXmQ,523
|
|
50
50
|
runtimepy/data/tftp_server.yaml,sha256=-bFOWJSagI-fEQQcT8k7eDMJVfSPm2XAxLVG3dqUTa4,204
|
|
51
|
-
runtimepy/data/css/bootstrap_extra.css,sha256=
|
|
51
|
+
runtimepy/data/css/bootstrap_extra.css,sha256=w1Y527gWUnfC40zfodA8AM49BwGQVsOOYOFUX657IF4,1378
|
|
52
52
|
runtimepy/data/css/main.css,sha256=h1iKkxg6-t7wTwNQvxDiD9mjpWrqq_FmgT6yXP7UANQ,688
|
|
53
53
|
runtimepy/data/js/DataConnection.js,sha256=DnX8FMehjJXqmI62UMYXSvl_XdfQMzq3XUDFbLu2GgI,98
|
|
54
54
|
runtimepy/data/js/JsonConnection.js,sha256=rclZrbmWc_zSs6I_JhOgxnVPFIyPMo5WdjAe8alyZ3o,2729
|
|
@@ -171,7 +171,7 @@ runtimepy/net/server/app/env/widgets.py,sha256=_kNvPl7MXnZOiwTjoZiU2hfuSjkLnRUrO
|
|
|
171
171
|
runtimepy/net/server/app/env/tab/__init__.py,sha256=stTVKyHljLQWnnhxkWPwa7bLdZtjhiMFbiVFgbiYaFI,647
|
|
172
172
|
runtimepy/net/server/app/env/tab/base.py,sha256=uBPpOeqI23341IezIQcGvJciPfIL2P5qQgbZ74aQRKA,991
|
|
173
173
|
runtimepy/net/server/app/env/tab/controls.py,sha256=hsj0ErywfmOBtJLNZbMISrE2ELJEfyXvtCtpsDbXlYg,4734
|
|
174
|
-
runtimepy/net/server/app/env/tab/html.py,sha256=
|
|
174
|
+
runtimepy/net/server/app/env/tab/html.py,sha256=ElAPyLczQVdja8OTWibKwgB0Sn2dklrc7DkqBFZxm_Y,7262
|
|
175
175
|
runtimepy/net/server/app/env/tab/message.py,sha256=3LLaEIJgr2hhZH2-v-Sq-OKfKkfRgP-RDU8EpKLYb74,3709
|
|
176
176
|
runtimepy/net/server/struct/__init__.py,sha256=z62I3DUoOnCcTv7C9X3sA6jOBKAJQ_uSOQA7uNwyrj4,1839
|
|
177
177
|
runtimepy/net/server/websocket/__init__.py,sha256=KISuFUUQwNn6BXo8BOMuMOXyoVqE7Jw94ZQiSCQuRQE,5279
|
|
@@ -194,8 +194,8 @@ runtimepy/net/udp/connection.py,sha256=YtLty6iveVH6PQRODKriwR5Q6lFi0Ed4k0o5r0bgA
|
|
|
194
194
|
runtimepy/net/udp/create.py,sha256=84YDfJbNBlN0ZwbNpvh6Dl7ZPecbZfmpjMNRRWcvJDk,2005
|
|
195
195
|
runtimepy/net/udp/protocol.py,sha256=A4SRHf0CgcL2zDs1nAsGDqz0RxKBy1soS8wtNdS5S0I,1492
|
|
196
196
|
runtimepy/net/udp/queue.py,sha256=DF-YscxQcGbGCYQLz_l_BMaSRfraZOhRwieTEdXLMds,637
|
|
197
|
-
runtimepy/net/udp/tftp/__init__.py,sha256=
|
|
198
|
-
runtimepy/net/udp/tftp/base.py,sha256=
|
|
197
|
+
runtimepy/net/udp/tftp/__init__.py,sha256=C4YI06y-xwHphYBc68jXL35CrLVNzds3-tIhxTp1PWk,9081
|
|
198
|
+
runtimepy/net/udp/tftp/base.py,sha256=7nEgxv3j6ehqP8q2p769NjnkkMBOw3smt1XDqFBmdN4,11551
|
|
199
199
|
runtimepy/net/udp/tftp/endpoint.py,sha256=so60LdPTG66N5tdhHhiX7j_TBHvNOTi4JIgLcg2MAm0,10890
|
|
200
200
|
runtimepy/net/udp/tftp/enums.py,sha256=06juMd__pJZsyL8zO8p3hRucnOratt1qtz9zcxzMg4s,1579
|
|
201
201
|
runtimepy/net/udp/tftp/io.py,sha256=w6cnUt-T-Ma6Vg8BWoRbsNnIWUv0HTY4am6bcLWxNJs,803
|
|
@@ -255,9 +255,9 @@ runtimepy/tui/task.py,sha256=nUZo9fuOC-k1Wpqdzkv9v1tQirCI28fZVgcC13Ijvus,1093
|
|
|
255
255
|
runtimepy/tui/channels/__init__.py,sha256=evDaiIn-YS9uGhdo8ZGtP9VK1ek6sr_P1nJ9JuSET0o,4536
|
|
256
256
|
runtimepy/ui/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
257
257
|
runtimepy/ui/controls.py,sha256=yvT7h3thbYaitsakcIAJ90EwKzJ4b-jnc6p3UuVf_XE,1241
|
|
258
|
-
runtimepy-5.4.
|
|
259
|
-
runtimepy-5.4.
|
|
260
|
-
runtimepy-5.4.
|
|
261
|
-
runtimepy-5.4.
|
|
262
|
-
runtimepy-5.4.
|
|
263
|
-
runtimepy-5.4.
|
|
258
|
+
runtimepy-5.4.4.dist-info/LICENSE,sha256=okYCYhGsx_BlzvFdoNVBVpw_Cfb4SOqHA_VAARml4Hc,1071
|
|
259
|
+
runtimepy-5.4.4.dist-info/METADATA,sha256=QwSQWMUYIK5S4grh2n898qjjXI_7gHHMFtU10gqAX7c,8152
|
|
260
|
+
runtimepy-5.4.4.dist-info/WHEEL,sha256=R0nc6qTxuoLk7ShA2_Y-UWkN8ZdfDBG2B6Eqpz2WXbs,91
|
|
261
|
+
runtimepy-5.4.4.dist-info/entry_points.txt,sha256=-btVBkYv7ybcopqZ_pRky-bEzu3vhbaG3W3Z7ERBiFE,51
|
|
262
|
+
runtimepy-5.4.4.dist-info/top_level.txt,sha256=0jPmh6yqHyyJJDwEID-LpQly-9kQ3WRMjH7Lix8peLg,10
|
|
263
|
+
runtimepy-5.4.4.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|