runtimepy 5.13.1__py3-none-any.whl → 5.13.2__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=25280d90363095aa6b5717f2105ff685
4
+ # hash=6693eae62108cbcdfbccdb9de6b57fa8
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.13.1"
13
+ VERSION = "5.13.2"
14
14
 
15
15
  # runtimepy-specific content.
16
16
  METRICS_NAME = "metrics"
@@ -0,0 +1,19 @@
1
+ ---
2
+ includes:
3
+ - package://runtimepy/factories.yaml
4
+
5
+ init:
6
+ - runtimepy.net.arbiter.housekeeping.init
7
+
8
+ config:
9
+ # Default redirects.
10
+ http_redirects:
11
+ "/": "/index.html"
12
+ "/index.html": "/app.html"
13
+
14
+ # Serve these applications by default at these paths.
15
+ http_app_paths: ["/app.html"]
16
+
17
+ # Handles config["http_app_prefixes"].
18
+ config_builders:
19
+ - runtimepy.net.html.arbiter.web_app_paths
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  includes:
3
- - package://runtimepy/factories.yaml
3
+ - package://runtimepy/base.yaml
4
4
 
5
5
  ports:
6
6
  - {name: runtimepy_http_server, type: tcp}
@@ -10,22 +10,6 @@ ports:
10
10
  structs:
11
11
  - {name: ui, factory: ui_state}
12
12
 
13
- init:
14
- - runtimepy.net.arbiter.housekeeping.init
15
-
16
- config:
17
- # Default redirects.
18
- http_redirects:
19
- "/": "/index.html"
20
- "/index.html": "/app.html"
21
-
22
- # Serve these applications by default at these paths.
23
- http_app_paths: ["/app.html"]
24
-
25
- # Handles config["http_app_prefixes"].
26
- config_builders:
27
- - runtimepy.net.html.arbiter.web_app_paths
28
-
29
13
  servers:
30
14
  - factory: runtimepy_http
31
15
  kwargs: {port: "$runtimepy_http_server"}
@@ -55,6 +55,12 @@ class RuntimepyServerConnection(HttpConnection):
55
55
  class_paths: list[Pathlike] = [Path(), package_data_dir()]
56
56
  class_redirect_paths: dict[Path, Union[str, Path]] = {}
57
57
 
58
+ # Set these to control meta attributes.
59
+ metadata: dict[str, Optional[str]] = {
60
+ "title": HttpConnection.identity,
61
+ "description": None,
62
+ }
63
+
58
64
  def add_path(self, path: Pathlike, front: bool = False) -> None:
59
65
  """Add a path."""
60
66
 
@@ -145,7 +151,16 @@ class RuntimepyServerConnection(HttpConnection):
145
151
  ) -> bytes:
146
152
  """Return rendered markdown content."""
147
153
 
148
- document = get_html()
154
+ meta: dict[str, str] = type(self).metadata.copy() # type: ignore
155
+
156
+ meta.setdefault("description", "")
157
+ meta["description"] += (
158
+ " This page was rendered from "
159
+ f"Markdown by {HttpConnection.identity}."
160
+ )
161
+
162
+ document = get_html(**meta)
163
+
149
164
  with IndentedFileWriter.string() as writer:
150
165
  writer.write_markdown(content, **kwargs)
151
166
  full_markdown_page(
@@ -336,6 +351,7 @@ class RuntimepyServerConnection(HttpConnection):
336
351
  response,
337
352
  request_data,
338
353
  default_app=type(self).default_app,
354
+ **type(self).metadata,
339
355
  )
340
356
 
341
357
  if populated:
@@ -68,6 +68,8 @@ async def setup(app: AppInfo) -> int:
68
68
  )
69
69
  )
70
70
 
71
+ RuntimepyServerConnection.metadata.update(app.config_param("html", {}))
72
+
71
73
  # Default application (environment tabs).
72
74
  html_app = create_app(app, getattr(_import_module(module), method))
73
75
  target: str
@@ -24,19 +24,32 @@ HtmlApps = dict[str, HtmlApp]
24
24
  def get_html(
25
25
  title: str = HttpConnection.identity,
26
26
  cache_control: str = "public",
27
+ description: str = None,
27
28
  **kwargs,
28
29
  ) -> Html:
29
30
  """Get a default HTML document."""
30
31
 
31
32
  elem = Html(title, **kwargs)
32
33
 
33
- elem.children.append(
34
+ elem.head.children.append(
34
35
  Element(
35
36
  tag="meta",
36
37
  attrib={"http-equiv": "Cache-Control", "content": cache_control},
37
38
  )
38
39
  )
39
40
 
41
+ elem.head.children.append(
42
+ Element(tag="link", rel="icon", href="/favicon.ico")
43
+ )
44
+
45
+ if description:
46
+ elem.head.children.append(
47
+ Element(
48
+ tag="meta",
49
+ attrib={"name": "description", "content": description},
50
+ )
51
+ )
52
+
40
53
  return elem
41
54
 
42
55
 
@@ -47,6 +60,7 @@ async def html_handler(
47
60
  response: ResponseHeader,
48
61
  request_data: Optional[bytes],
49
62
  default_app: HtmlApp = None,
63
+ **kwargs,
50
64
  ) -> bool:
51
65
  """Render an HTML document in response to an HTTP request."""
52
66
 
@@ -56,6 +70,8 @@ async def html_handler(
56
70
  # Create the application.
57
71
  app = apps.get(request.target.path, default_app)
58
72
  if app is not None:
59
- (await app(get_html(), request, response, request_data)).render(stream)
73
+ (
74
+ await app(get_html(**kwargs), request, response, request_data)
75
+ ).render(stream)
60
76
 
61
77
  return app is not None
@@ -52,10 +52,13 @@ def to_json(response: HttpResponse) -> Any:
52
52
  )
53
53
 
54
54
 
55
+ IDENTITY = f"{PKG_NAME}/{VERSION}"
56
+
57
+
55
58
  class HttpConnection(_TcpConnection):
56
59
  """A class implementing a basic HTTP interface."""
57
60
 
58
- identity = f"{PKG_NAME}/{VERSION}"
61
+ identity = IDENTITY
59
62
 
60
63
  expecting_response: bool
61
64
 
@@ -1,5 +1,5 @@
1
1
  aiofiles
2
- vcorelib>=3.5.1
2
+ vcorelib>=3.5.8
3
3
  svgen>=0.7.12
4
4
  websockets
5
5
  psutil
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: runtimepy
3
- Version: 5.13.1
3
+ Version: 5.13.2
4
4
  Summary: A framework for implementing Python services.
5
5
  Home-page: https://github.com/libre-embedded/runtimepy
6
6
  Author: Libre Embedded
@@ -18,10 +18,10 @@ Requires-Python: >=3.12
18
18
  Description-Content-Type: text/markdown
19
19
  License-File: LICENSE
20
20
  Requires-Dist: aiofiles
21
- Requires-Dist: websockets
22
- Requires-Dist: vcorelib>=3.5.1
23
- Requires-Dist: svgen>=0.7.12
21
+ Requires-Dist: vcorelib>=3.5.8
24
22
  Requires-Dist: psutil
23
+ Requires-Dist: svgen>=0.7.12
24
+ Requires-Dist: websockets
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=69775d79c8c13f44e0ac000acdeb93e2
54
+ hash=f3bcab8765e649f1b80ad504e5debde9
55
55
  =====================================
56
56
  -->
57
57
 
58
- # runtimepy ([5.13.1](https://pypi.org/project/runtimepy/))
58
+ # runtimepy ([5.13.2](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,11 +1,11 @@
1
- runtimepy/__init__.py,sha256=VPZ8WIQEUlyrEvvx7lZX4lLKZya3zWUCRU_k28pfybs,391
1
+ runtimepy/__init__.py,sha256=SS-yzin_UgsO_Yr3uFKIDgmWSOp6OCzrOj3rb2DZ0Qo,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
5
5
  runtimepy/entry.py,sha256=DGHLv_SmTMImRcWjbVa2dKiWkhvAbxZwuvtvWLbx5U4,1954
6
6
  runtimepy/mapping.py,sha256=VQK1vzmQVvYYKI85_II37-hIEbvgL3PzNy-WI6TTo80,5091
7
7
  runtimepy/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
- runtimepy/requirements.txt,sha256=-yAmlSgsSmAprzeYuyO4l8uUxlDj_XnFA0F8yyw5dBw,125
8
+ runtimepy/requirements.txt,sha256=uc8eW9HzoBsDmspEvyDKIs-xGrWs_UUltwAQCk072PU,125
9
9
  runtimepy/schemas.py,sha256=zTgxPm9DHZ0R_bmmOjNQMTXdtM_Hb1bE-Fog40jDCgg,839
10
10
  runtimepy/util.py,sha256=ZHSucNi-gbrcajoCv2dNjQs48dJPC3mTM_wZHx7AW1U,1719
11
11
  runtimepy/channel/__init__.py,sha256=pf0RJ5g37_FVV8xoUNgzFGuIfbZEYSBA_cQlJSDTPDo,4774
@@ -42,13 +42,14 @@ runtimepy/control/source.py,sha256=nW3Q2D-LcekII7K5XKbxXCcR-9jYQyvv0UypeNy1Dnw,1
42
42
  runtimepy/control/step.py,sha256=2LdZTpMHLwHLdpPVinpC2qByTs5I5LTDt-xONn_6Fc8,5491
43
43
  runtimepy/control/env/__init__.py,sha256=RHJqysY7Pv4VDs2SGk0X-qc5xp_SrQ_oxb5Deug8HEM,1339
44
44
  runtimepy/data/404.html,sha256=D_nhuj1AfO5EaIVsajknfaeZ5cVDKCNRPtUY4MHg1Xc,5326
45
+ runtimepy/data/base.yaml,sha256=WGy2nPiRZk5_wBU7BlWaFfCnzRprJBp-m8onOPUoLAo,399
45
46
  runtimepy/data/browser.yaml,sha256=oc5KEV1C1uAJ4MkhNo4hyVVfJtZvHelRNqzNvD313Ow,79
46
47
  runtimepy/data/dummy_load.yaml,sha256=PfKRXXgZnENRMSd68eznSMTV8xanVH5JY4FmoZRPFGY,1985
47
48
  runtimepy/data/factories.yaml,sha256=esuoouMre8w7siZfBoZKqC-5myghJ_WwOOCDIq135zg,1899
48
49
  runtimepy/data/favicon.ico,sha256=boxAGaHbUjMFrOO2TZpsO0nIRC-LUgwHVQYOiG1YQnM,362870
49
50
  runtimepy/data/sample_telemetry.yaml,sha256=OpdFurkvtWJGaNl9LMlU2rKo15AaVVr-U_hoZfsbp-Y,695
50
51
  runtimepy/data/server.yaml,sha256=wS_Ceiu2TpkfPurpqoYoPlgzc9DAWtUd24MW7t-S5rU,97
51
- runtimepy/data/server_base.yaml,sha256=R_varVgGPGV4nxWYYwKUnHC9ufINi4V92YVhxCCC5wg,875
52
+ runtimepy/data/server_base.yaml,sha256=Fiqz9C_ikxtYYFO8q17XzgaY5b3H9RuyqJr-QoTk-qg,524
52
53
  runtimepy/data/server_dev.yaml,sha256=nQsPh7LuQig3pzHfdg_aD3yOUiCj1sKKfI-WwW3hXmQ,523
53
54
  runtimepy/data/tftp_server.yaml,sha256=-bFOWJSagI-fEQQcT8k7eDMJVfSPm2XAxLVG3dqUTa4,204
54
55
  runtimepy/data/css/bootstrap_extra.css,sha256=kJLOp8j-vRxnWzQOf_eOz4kL8Mbrwxuwk3YNh90HgWM,1907
@@ -193,11 +194,11 @@ runtimepy/net/http/request_target.py,sha256=EE1aI5VSARw1h93jyZvP56ir5O5fjd6orYK-
193
194
  runtimepy/net/http/response.py,sha256=y33KLUJNE7zx6biUMwTkUfQ1bXiKV6pjrcxuh8U3WCE,3216
194
195
  runtimepy/net/http/state.py,sha256=qCMN8aWfCRfU9XP-cIhSOo2RqfljTjbQRCflfcy2bfY,1626
195
196
  runtimepy/net/http/version.py,sha256=mp6rgIM7-VUVKLCA0Uw96CmBkL0ET860lDVVEewpZ7w,1098
196
- runtimepy/net/server/__init__.py,sha256=FRwHGxga52NXoaKBkjfWoVpDW5hkQaQzOrx0-gCvkos,10861
197
- runtimepy/net/server/html.py,sha256=Z0WwAgncx-BTdT9Nm5L6KuambJIjuyw7wVvzI4dMxTg,1514
197
+ runtimepy/net/server/__init__.py,sha256=LqN4NSkk_B0sv-i1PMv98kzkMGCCVbAPTxst1Xgjq6Y,11340
198
+ runtimepy/net/server/html.py,sha256=TZ2ZSPTxgA6KAKS26tNrSUpxFUrdk92K5zP2ybcSYqs,1892
198
199
  runtimepy/net/server/json.py,sha256=a7vM5yfq2er4DexzFqEMnxoMGDeuywKkVH4-uNJBAik,2522
199
200
  runtimepy/net/server/markdown.py,sha256=3kLQR3fsGFU8dUiDuMbUiLv7XKx9s4zXy9SZsJDDc9Y,1507
200
- runtimepy/net/server/app/__init__.py,sha256=beU67t7zoKGlO7aldjQMUwYLm9mSlc78eMQazri-otw,3012
201
+ runtimepy/net/server/app/__init__.py,sha256=_Hmbhu2TvO1aUrxfExbOi5qW9LNVTti8-ndwLpYrhjA,3089
201
202
  runtimepy/net/server/app/base.py,sha256=46aOqZwRss_nh_WfEH1cMJ9GUVoLJjERd7cTRFu6mXE,1878
202
203
  runtimepy/net/server/app/create.py,sha256=eRT8qxubht5A7149Xol3Z8rkdYd_pjNLqrlyMnXk-Zg,2660
203
204
  runtimepy/net/server/app/elements.py,sha256=KJt9vWqkfvniJMiLOJN467JjPPrEqJYZXmDuY1JoY1g,455
@@ -227,7 +228,7 @@ runtimepy/net/tcp/__init__.py,sha256=OOWohegpoioSTf8M7uDf-4EV1IDungz7-U19L_2yW4I
227
228
  runtimepy/net/tcp/connection.py,sha256=sYWj2aDiAHQf70zfRJM24cHraFd_TuzTD4fRWeSQZXE,8811
228
229
  runtimepy/net/tcp/create.py,sha256=zZsRs5KYpO3bNGh-DwEOEzjUDE4ixj-UBHYgZ0GvC7c,2013
229
230
  runtimepy/net/tcp/protocol.py,sha256=vEnIX3gUX2nrw9ofT_e4KYU4VY2k4WP0WuOi4eE_OOQ,1444
230
- runtimepy/net/tcp/http/__init__.py,sha256=lxEQsc8Mv5Qs0F9W-t8XBb2JPQQLpMqHYJM8NMXm-Dc,6206
231
+ runtimepy/net/tcp/http/__init__.py,sha256=nXgUoC7jKlR7Ay7cTkomU2u_TcTsoO38uastZSBGa9k,6228
231
232
  runtimepy/net/tcp/scpi/__init__.py,sha256=aWCWQfdeyfoU9bpOnOtyIQbT1swl4ergXLFn5kXAH28,2105
232
233
  runtimepy/net/tcp/telnet/__init__.py,sha256=96eJFb301I3H2ivDtGMQtDDw09Xm5NRvM9VEC-wjt8c,4768
233
234
  runtimepy/net/tcp/telnet/codes.py,sha256=1-yyRe-Kz_W7d6B0P3iT1AaSNR3_Twmn-MUjKCJJknY,3518
@@ -300,9 +301,9 @@ runtimepy/tui/task.py,sha256=nUZo9fuOC-k1Wpqdzkv9v1tQirCI28fZVgcC13Ijvus,1093
300
301
  runtimepy/tui/channels/__init__.py,sha256=evDaiIn-YS9uGhdo8ZGtP9VK1ek6sr_P1nJ9JuSET0o,4536
301
302
  runtimepy/ui/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
302
303
  runtimepy/ui/controls.py,sha256=yvT7h3thbYaitsakcIAJ90EwKzJ4b-jnc6p3UuVf_XE,1241
303
- runtimepy-5.13.1.dist-info/licenses/LICENSE,sha256=yKBRwbO-cOPBrlpsZmJkkSa33DfY31aE8t7lZ0DwlUo,1071
304
- runtimepy-5.13.1.dist-info/METADATA,sha256=5e7rbi_qozv3poWPC2SoeRRE74fdJYM0CK57kb4BBKY,9269
305
- runtimepy-5.13.1.dist-info/WHEEL,sha256=GHB6lJx2juba1wDgXDNlMTyM13ckjBMKf-OnwgKOCtA,91
306
- runtimepy-5.13.1.dist-info/entry_points.txt,sha256=-btVBkYv7ybcopqZ_pRky-bEzu3vhbaG3W3Z7ERBiFE,51
307
- runtimepy-5.13.1.dist-info/top_level.txt,sha256=0jPmh6yqHyyJJDwEID-LpQly-9kQ3WRMjH7Lix8peLg,10
308
- runtimepy-5.13.1.dist-info/RECORD,,
304
+ runtimepy-5.13.2.dist-info/licenses/LICENSE,sha256=yKBRwbO-cOPBrlpsZmJkkSa33DfY31aE8t7lZ0DwlUo,1071
305
+ runtimepy-5.13.2.dist-info/METADATA,sha256=_GkgF9xsxR9UGBpUSeJ0of9xjc783dgtAMH8GltwoRs,9269
306
+ runtimepy-5.13.2.dist-info/WHEEL,sha256=0CuiUZ_p9E4cD6NyLD6UG80LBXYyiSYZOKDm5lp32xk,91
307
+ runtimepy-5.13.2.dist-info/entry_points.txt,sha256=-btVBkYv7ybcopqZ_pRky-bEzu3vhbaG3W3Z7ERBiFE,51
308
+ runtimepy-5.13.2.dist-info/top_level.txt,sha256=0jPmh6yqHyyJJDwEID-LpQly-9kQ3WRMjH7Lix8peLg,10
309
+ runtimepy-5.13.2.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (80.3.0)
2
+ Generator: setuptools (80.3.1)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5