runtimepy 5.15.0__py3-none-any.whl → 5.15.1__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 CHANGED
@@ -1,7 +1,7 @@
1
1
  # =====================================
2
2
  # generator=datazen
3
3
  # version=3.2.3
4
- # hash=58f166da9bc0561c671ef04c334d585d
4
+ # hash=7da25db9f79bc00e444a7898020e2a26
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.15.0"
13
+ VERSION = "5.15.1"
14
14
 
15
15
  # runtimepy-specific content.
16
16
  METRICS_NAME = "metrics"
@@ -85,6 +85,9 @@ structs:
85
85
 
86
86
  - name: example.struct3
87
87
  factory: sample_struct
88
+ config:
89
+ js_uris:
90
+ - package://runtimepy/js/sample.js
88
91
 
89
92
  # Sample peer processes.
90
93
  processes:
@@ -0,0 +1 @@
1
+ console.log(`sample.js included (${tab.name})`);
@@ -250,9 +250,9 @@ class Connection(
250
250
  await backoff.sleep()
251
251
  if await self.restart():
252
252
  self._set_enabled(True)
253
- self._restarts.raw.value += 1
253
+ self._restarts.increment()
254
254
 
255
- self._restart_attempts.raw.value += 1
255
+ self._restart_attempts.increment()
256
256
 
257
257
  @asynccontextmanager
258
258
  async def process_then_disable(self, **kwargs) -> AsyncIterator[None]:
@@ -40,6 +40,7 @@ def populate_tabs(app: AppInfo, tabs: TabbedContent) -> None:
40
40
  tabs,
41
41
  icon="arrow-repeat",
42
42
  markdown=task.markdown,
43
+ js_uris=task.config.get("js_uris", []),
43
44
  ).entry()
44
45
 
45
46
  # Struct tabs.
@@ -51,6 +52,7 @@ def populate_tabs(app: AppInfo, tabs: TabbedContent) -> None:
51
52
  tabs,
52
53
  icon="bucket",
53
54
  markdown=struct.markdown,
55
+ js_uris=struct.config.get("js_uris", []),
54
56
  ).entry()
55
57
 
56
58
  # Subprocess tabs.
@@ -28,12 +28,13 @@ class ChannelEnvironmentTabBase(Tab, LoggerMixin, MarkdownMixin):
28
28
  tabs: TabbedContent,
29
29
  icon: str = "alarm",
30
30
  markdown: str = None,
31
+ **kwargs,
31
32
  ) -> None:
32
33
  """Initialize this instance."""
33
34
 
34
35
  self.command = command
35
36
  self.set_markdown(markdown=markdown, package=PKG_NAME)
36
- super().__init__(name, app, tabs, source="env", icon=icon)
37
+ super().__init__(name, app, tabs, source="env", icon=icon, **kwargs)
37
38
 
38
39
  # Logging.
39
40
  LoggerMixin.__init__(self, logger=self.command.logger)
@@ -4,7 +4,7 @@ A module implementing an application tab interface.
4
4
 
5
5
  # built-in
6
6
  from io import StringIO
7
- from typing import cast
7
+ from typing import Iterable, cast
8
8
 
9
9
  # third-party
10
10
  from svgen.element import Element
@@ -29,6 +29,7 @@ class Tab:
29
29
  source: str = None,
30
30
  subdir: str = "tab",
31
31
  icon: str = None,
32
+ js_uris: Iterable[str] = None,
32
33
  ) -> None:
33
34
  """Initialize this instance."""
34
35
 
@@ -46,6 +47,10 @@ class Tab:
46
47
  button_str += self.name
47
48
  self.button.text = button_str
48
49
 
50
+ if not js_uris:
51
+ js_uris = []
52
+ self.js_uris: list[str] = list(js_uris)
53
+
49
54
  self.init()
50
55
 
51
56
  self.compose(self.content)
@@ -59,8 +64,12 @@ class Tab:
59
64
  def write_js(self, writer: IndentedFileWriter, **kwargs) -> bool:
60
65
  """Write JavaScript code for the tab."""
61
66
 
62
- return write_found_file(
63
- writer, kind_url("js", self.source, subdir=self.subdir, **kwargs)
67
+ return all(
68
+ write_found_file(writer, uri)
69
+ for uri in [
70
+ kind_url("js", self.source, subdir=self.subdir, **kwargs)
71
+ ]
72
+ + self.js_uris
64
73
  )
65
74
 
66
75
  def entry(self) -> None:
@@ -9,7 +9,9 @@ from typing import Iterable, cast
9
9
 
10
10
  # third-party
11
11
  from vcorelib.io.file_writer import IndentedFileWriter
12
+ from vcorelib.math.time import byte_count_str
12
13
  from vcorelib.paths import rel
14
+ from vcorelib.paths import stats as _stats
13
15
 
14
16
  LOGO_MARKDOWN = "[![logo](/static/png/chip-circle-bootstrap/128x128.png)](/)"
15
17
  DIR_FILE = "dir.html"
@@ -46,6 +48,8 @@ def markdown_for_dir(
46
48
  if curr_dir != Path():
47
49
  writer.write(f"* [..](/{curr_dir.parent}/{DIR_FILE})")
48
50
 
51
+ writer.write("| name | size |")
52
+ writer.write("|------|------|")
49
53
  for item in sorted(path.iterdir()):
50
54
  curr = rel(item, base=base)
51
55
 
@@ -53,7 +57,14 @@ def markdown_for_dir(
53
57
  if item.is_dir():
54
58
  name = f"**{name}**"
55
59
 
56
- writer.write(f"* [{name}](/{curr})")
60
+ stats = _stats(item)
61
+ assert stats
62
+ size_str = (
63
+ byte_count_str(stats.st_size) if item.is_file() else ""
64
+ )
65
+ writer.write(f"| [{name}](/{curr}) | {size_str} |")
66
+
67
+ writer.empty()
57
68
 
58
69
  result: str = cast(StringIO, writer.stream).getvalue()
59
70
 
@@ -29,6 +29,7 @@ from websockets.asyncio.server import serve as _serve
29
29
  from websockets.exceptions import ConnectionClosed as _ConnectionClosed
30
30
 
31
31
  # internal
32
+ from runtimepy.net import normalize_host as _normalize_host
32
33
  from runtimepy.net import sockname as _sockname
33
34
  from runtimepy.net.connection import Connection
34
35
  from runtimepy.net.connection import EchoConnection as _EchoConnection
@@ -64,7 +65,13 @@ class WebsocketConnection(Connection):
64
65
  """Initialize this connection."""
65
66
 
66
67
  self.protocol = protocol
67
- super().__init__(self.protocol.logger, **kwargs)
68
+ super().__init__(
69
+ _getLogger(
70
+ f"W {_normalize_host(*self.protocol.local_address)} -> "
71
+ f"{_normalize_host(*self.protocol.remote_address)}"
72
+ ),
73
+ **kwargs,
74
+ )
68
75
 
69
76
  # Store connection-instantiation arguments (for connection restarting).
70
77
  self._uri: str = ""
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: runtimepy
3
- Version: 5.15.0
3
+ Version: 5.15.1
4
4
  Summary: A framework for implementing Python services.
5
5
  Home-page: https://github.com/libre-embedded/runtimepy
6
6
  Author: Libre Embedded
@@ -17,11 +17,11 @@ Classifier: Development Status :: 5 - Production/Stable
17
17
  Requires-Python: >=3.12
18
18
  Description-Content-Type: text/markdown
19
19
  License-File: LICENSE
20
+ Requires-Dist: vcorelib>=3.6.2
20
21
  Requires-Dist: websockets
21
- Requires-Dist: psutil
22
22
  Requires-Dist: svgen>=0.8.0
23
23
  Requires-Dist: aiofiles
24
- Requires-Dist: vcorelib>=3.6.2
24
+ Requires-Dist: psutil
25
25
  Provides-Extra: test
26
26
  Requires-Dist: pylint; extra == "test"
27
27
  Requires-Dist: flake8; extra == "test"
@@ -51,11 +51,11 @@ Dynamic: requires-python
51
51
  =====================================
52
52
  generator=datazen
53
53
  version=3.2.3
54
- hash=db8f45762873863c99d4d7d8f996d2fb
54
+ hash=21dc494ffe783ac9edf7769c4d5aa21e
55
55
  =====================================
56
56
  -->
57
57
 
58
- # runtimepy ([5.15.0](https://pypi.org/project/runtimepy/))
58
+ # runtimepy ([5.15.1](https://pypi.org/project/runtimepy/))
59
59
 
60
60
  [![python](https://img.shields.io/pypi/pyversions/runtimepy.svg)](https://pypi.org/project/runtimepy/)
61
61
  ![Build Status](https://github.com/libre-embedded/runtimepy/workflows/Python%20Package/badge.svg)
@@ -1,4 +1,4 @@
1
- runtimepy/__init__.py,sha256=b_ptd8WNjZK1zK_FHN2DmLkBIzyqoGLd67n3xangX6g,391
1
+ runtimepy/__init__.py,sha256=fFFYCw5EFe16Vfqrut6lO_EODvjbdb7fbzjzBldFfq4,391
2
2
  runtimepy/__main__.py,sha256=IKioH2xOtsXwrwb9zABDQEJvuAX--Lnh84TeSz0XSs0,332
3
3
  runtimepy/app.py,sha256=Er1ZKKrG9U0FV0gQg_GYF9xDb89HgYnVzS5SjxGa2Tg,970
4
4
  runtimepy/dev_requirements.txt,sha256=VZhW6bJ5YbwaoN4d_XxZFuN5BbDLaG7ngKrGnugVPRw,245
@@ -45,7 +45,7 @@ runtimepy/control/env/__init__.py,sha256=RHJqysY7Pv4VDs2SGk0X-qc5xp_SrQ_oxb5Deug
45
45
  runtimepy/data/404.md,sha256=_yzjvp2GeMc5OBvZX2zDbX-Ns6T7HCO9esRbS5PmkXU,397
46
46
  runtimepy/data/base.yaml,sha256=PEsvcMV1qFb1Gr6Cx2SgmR6ScfPyuu3yTdnvSBTVSdA,453
47
47
  runtimepy/data/browser.yaml,sha256=oc5KEV1C1uAJ4MkhNo4hyVVfJtZvHelRNqzNvD313Ow,79
48
- runtimepy/data/dummy_load.yaml,sha256=BVzCn7CmvcSNcDNWWYoAdil3-YQMdxuwTOCh2dpRR5s,2001
48
+ runtimepy/data/dummy_load.yaml,sha256=oAuccgvM3lDoN5RZBo4UECiegxzOgpllBfXXwZ5odCw,2071
49
49
  runtimepy/data/factories.yaml,sha256=CdpnjK2glj8HewI2tFSNvCSUdcNPeVD_tFbGy2QBSQg,1952
50
50
  runtimepy/data/favicon.ico,sha256=boxAGaHbUjMFrOO2TZpsO0nIRC-LUgwHVQYOiG1YQnM,362870
51
51
  runtimepy/data/sample_telemetry.yaml,sha256=OpdFurkvtWJGaNl9LMlU2rKo15AaVVr-U_hoZfsbp-Y,695
@@ -63,6 +63,7 @@ runtimepy/data/js/events.js,sha256=rgz3Q_8J6sfU_7Sa7fG1mZD0pQ4S3vwN2mqcvQfePkM,5
63
63
  runtimepy/data/js/init.js,sha256=6RhwGRl_DBjMpztms2JOQiQlvdizcLeaiETNEh31KyU,1992
64
64
  runtimepy/data/js/main.js,sha256=nYIQ6O76EWqlzwX7oEwPXqC-LCUFCZYDADK9QbYRDKk,404
65
65
  runtimepy/data/js/markdown_page.js,sha256=R7Z2CwCk0dXED_4lwvDMXRNNB9ki9RvfwEKLPSwNWec,982
66
+ runtimepy/data/js/sample.js,sha256=Q8UhPKNNrkQ7yFd5p1xqWNerVJ-s8WHJSAYn2ohUkNE,49
66
67
  runtimepy/data/js/util.js,sha256=Xc8pHUiFDBDvIqTamWrCYUOpF7iR9VNvPDCSCQAfLDA,1424
67
68
  runtimepy/data/js/worker.js,sha256=V9deGAynjvUr1D-WGi3wUW8rxoaNLvBvayMoLFZk3w0,2444
68
69
  runtimepy/data/js/classes/App.js,sha256=t3XVC7zSi8L_sMJ4KP-lyWyuD4cysCKkptN-lgjewN8,5159
@@ -158,7 +159,7 @@ runtimepy/mixins/regex.py,sha256=kpCj4iL1akzt_KPPiMP-bTbuLBHOpkUrwbCTRe8HSUk,106
158
159
  runtimepy/mixins/trig.py,sha256=vkDd9Rh8080gvH5OHkSYmjImVgM_ZZ7RzMxsczKx5N4,2480
159
160
  runtimepy/net/__init__.py,sha256=HQaWGxnEH49JSPX2Q_N5QNSV0Wd_x0zZQJa1SV1EC_M,790
160
161
  runtimepy/net/backoff.py,sha256=IVloxQd-gEK62gFAlU2aOwgTEXhsNUTBfS16eiOqKG8,1080
161
- runtimepy/net/connection.py,sha256=5rjdfqq58DU5XW5eaZgkO8vIjENYiNLtzE7iV1uWvxk,12878
162
+ runtimepy/net/connection.py,sha256=GZ9rZP7wgUUYWmyL4FGbJzhqb1uNWCQAsNbXSGzoHAw,12872
162
163
  runtimepy/net/manager.py,sha256=-M-ZSB9izay6HK1ytTayAYnSHYAz34dcwxaiNhC4lWg,4264
163
164
  runtimepy/net/mixin.py,sha256=0NTKeuaoUNm7--GzA7rxU3gb1rrGGhu1vNj6mek4dDA,3022
164
165
  runtimepy/net/mtu.py,sha256=XnLXAFMsDxK1Lj5v_zgWaBrC3lNqf81DkbDc6hpMdmI,3495
@@ -200,7 +201,7 @@ runtimepy/net/http/version.py,sha256=mp6rgIM7-VUVKLCA0Uw96CmBkL0ET860lDVVEewpZ7w
200
201
  runtimepy/net/server/__init__.py,sha256=5KalIcOWv8lYm8747pq2rzGwpLz713XdHuQIKbWJsXc,11649
201
202
  runtimepy/net/server/html.py,sha256=OB2K37kA7MHtcKqp0pZE1q_XgiyvfooigzS0-OQFCCM,1900
202
203
  runtimepy/net/server/json.py,sha256=AaMPw-G-7xX67mf1LvQAipNdwrnmbLDunVlkWf6iOz0,2526
203
- runtimepy/net/server/markdown.py,sha256=AvwWQg7DgMSroOxNN0KEKwpPoLueNvv2GSBdPzQbMvI,1734
204
+ runtimepy/net/server/markdown.py,sha256=UIJ9R9WM5XodPs8WEevFNJ3LX9tMevhUe8QKKdeY4ak,2143
204
205
  runtimepy/net/server/mux.py,sha256=ejET7NpJzzJjkVwR8laSuZYR79DOT3XazmAIm6rENSE,598
205
206
  runtimepy/net/server/app/__init__.py,sha256=0eCcqYvmby_wQTGqAiGbGM5LCxKM2qpjuIT0gLHsoDU,3157
206
207
  runtimepy/net/server/app/base.py,sha256=46aOqZwRss_nh_WfEH1cMJ9GUVoLJjERd7cTRFu6mXE,1878
@@ -211,13 +212,13 @@ runtimepy/net/server/app/landing_page.py,sha256=9TXpL0ITYWCxw9Potq71ZOwLlIlMegcK
211
212
  runtimepy/net/server/app/placeholder.py,sha256=OuiMNvLEK0pI2N3oIqvPRaperoJkDg-fBds9HHfuosg,1664
212
213
  runtimepy/net/server/app/pyodide.py,sha256=dGJ4u78eYQLU9RQbZEWgzv-7jVIwblS6VopibG82tA4,478
213
214
  runtimepy/net/server/app/sound.py,sha256=qG2k00nWRPAmI5_4L_LMs10nsCTBKaAzIp80embgua8,837
214
- runtimepy/net/server/app/tab.py,sha256=gRiaUJdB3V9hIKI5MksW7spNChfMtEMDFWCTP1ERrZ4,2272
215
- runtimepy/net/server/app/env/__init__.py,sha256=IYk_DuedEQRp1rzKCi1FT4xks_RI-XGTsWh5zJtZkYc,4771
215
+ runtimepy/net/server/app/tab.py,sha256=N4NYvxeo0fllb404aCHn7YKhlY6ZnG6G4HBiMS17qQY,2510
216
+ runtimepy/net/server/app/env/__init__.py,sha256=vgiPIYkitx0aqtmgG_nkOehDM7vrQJHYkhRsGCP8pU8,4877
216
217
  runtimepy/net/server/app/env/modal.py,sha256=HTipCYgQaAUtsmlBjXKfhAM5JyhLqoIIwEwsPnKhrG8,1740
217
218
  runtimepy/net/server/app/env/settings.py,sha256=m87hHAapuNq0xKzDNSNTwG8D2Cb3QFSVrziszf8iVHs,1631
218
219
  runtimepy/net/server/app/env/widgets.py,sha256=sDfJYBVIXZuly4Rvch597Y-LTT6t3obxc60oejqGv7g,7104
219
220
  runtimepy/net/server/app/env/tab/__init__.py,sha256=stTVKyHljLQWnnhxkWPwa7bLdZtjhiMFbiVFgbiYaFI,647
220
- runtimepy/net/server/app/env/tab/base.py,sha256=QBTBBvsdihbzK5MqrJBf6K5N61b3i8Ms0P6Xq_h1mbs,1171
221
+ runtimepy/net/server/app/env/tab/base.py,sha256=mljE6n56HUwcWO1lrjj5PR7qh5dvY8CZYMwDcrV-yVk,1199
221
222
  runtimepy/net/server/app/env/tab/controls.py,sha256=11TidvphKyvLCgdW8Sjiyd6BpX4-ybGZPEhrn-hzkuU,8263
222
223
  runtimepy/net/server/app/env/tab/html.py,sha256=MbEQzxEPNcMCntGGm2qWli6ND_Ina46CEVzt7HF2yBg,8210
223
224
  runtimepy/net/server/app/env/tab/message.py,sha256=-J8wBo1KH0XoBi9VcUvl9LXZCaoFAmvFyMf_YFJVF6Q,3945
@@ -248,7 +249,7 @@ runtimepy/net/udp/tftp/endpoint.py,sha256=so60LdPTG66N5tdhHhiX7j_TBHvNOTi4JIgLcg
248
249
  runtimepy/net/udp/tftp/enums.py,sha256=06juMd__pJZsyL8zO8p3hRucnOratt1qtz9zcxzMg4s,1579
249
250
  runtimepy/net/udp/tftp/io.py,sha256=w6cnUt-T-Ma6Vg8BWoRbsNnIWUv0HTY4am6bcLWxNJs,803
250
251
  runtimepy/net/websocket/__init__.py,sha256=YjSmoxiigmsI_hcQw6nueX7bxhrRGerEERnPvgLVEVA,313
251
- runtimepy/net/websocket/connection.py,sha256=VS1ifMrpIOiqvUakZWSGypqTZEWTMXhjRDiGMJ2gkZs,10129
252
+ runtimepy/net/websocket/connection.py,sha256=THrqy_WmwFuiNkojQ6pTUhBTJdokvWbH-3DsB96zCLU,10370
252
253
  runtimepy/noise/__init__.py,sha256=EJM7h3t_z74wwrn6FAFQwYE2yUcOZQ1K1IQqOb8Z0AI,384
253
254
  runtimepy/primitives/__init__.py,sha256=g5IK6e_UZuGhj9QNYoCn5TbhNatWX0nEYUs-JzsOizQ,2618
254
255
  runtimepy/primitives/base.py,sha256=6N_mfTuv0RJJYofSQQ858vJfgcTvjjvfXeebMw_1bw8,9339
@@ -305,9 +306,9 @@ runtimepy/tui/task.py,sha256=nUZo9fuOC-k1Wpqdzkv9v1tQirCI28fZVgcC13Ijvus,1093
305
306
  runtimepy/tui/channels/__init__.py,sha256=evDaiIn-YS9uGhdo8ZGtP9VK1ek6sr_P1nJ9JuSET0o,4536
306
307
  runtimepy/ui/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
307
308
  runtimepy/ui/controls.py,sha256=L55Af-4vGq6ZHewdoA7C_mAYq35WXl8NzOdcsmQIo7M,1868
308
- runtimepy-5.15.0.dist-info/licenses/LICENSE,sha256=yKBRwbO-cOPBrlpsZmJkkSa33DfY31aE8t7lZ0DwlUo,1071
309
- runtimepy-5.15.0.dist-info/METADATA,sha256=Hr1TYcveiC09pGHx5nro_VVvBfy3y1upL9vOgyTO0p4,9268
310
- runtimepy-5.15.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
311
- runtimepy-5.15.0.dist-info/entry_points.txt,sha256=-btVBkYv7ybcopqZ_pRky-bEzu3vhbaG3W3Z7ERBiFE,51
312
- runtimepy-5.15.0.dist-info/top_level.txt,sha256=0jPmh6yqHyyJJDwEID-LpQly-9kQ3WRMjH7Lix8peLg,10
313
- runtimepy-5.15.0.dist-info/RECORD,,
309
+ runtimepy-5.15.1.dist-info/licenses/LICENSE,sha256=yKBRwbO-cOPBrlpsZmJkkSa33DfY31aE8t7lZ0DwlUo,1071
310
+ runtimepy-5.15.1.dist-info/METADATA,sha256=3j48z5hnAIZFf5Nf3sQNIHAmDou7FrpFtm9YAwy6MD8,9268
311
+ runtimepy-5.15.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
312
+ runtimepy-5.15.1.dist-info/entry_points.txt,sha256=-btVBkYv7ybcopqZ_pRky-bEzu3vhbaG3W3Z7ERBiFE,51
313
+ runtimepy-5.15.1.dist-info/top_level.txt,sha256=0jPmh6yqHyyJJDwEID-LpQly-9kQ3WRMjH7Lix8peLg,10
314
+ runtimepy-5.15.1.dist-info/RECORD,,