runtimepy 5.13.1__py3-none-any.whl → 5.13.3__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=940af0fb662bf9b9e98e5ce5df85b4b2
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.3"
14
14
 
15
15
  # runtimepy-specific content.
16
16
  METRICS_NAME = "metrics"
runtimepy/data/404.html CHANGED
@@ -1,6 +1,7 @@
1
- <html lang=en><meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1"><title>runtimepy/5.12.0</title><style>@font-face{font-family:CascadiaCode;src:url(/static/woff2/CascadiaCode-Regular.woff2)}@font-face{font-family:CascadiaCode;src:url(/static/woff2/CascadiaCode-Bold.woff2);font-weight:700}@font-face{font-family:CascadiaCode;src:url(/static/woff2/CascadiaCode-BoldItalic.woff2);font-weight:700;font-style:italic}@font-face{font-family:CascadiaCode;src:url(/static/woff2/CascadiaCode-Italic.woff2);font-style:italic}@font-face{font-family:CascadiaMono;src:url(/static/woff2/CascadiaMono-Regular.woff2)}@font-face{font-family:CascadiaMono;src:url(/static/woff2/CascadiaMono-Bold.woff2);font-weight:700}@font-face{font-family:CascadiaMono;src:url(/static/woff2/CascadiaMono-BoldItalic.woff2);font-weight:700;font-style:italic}@font-face{font-family:CascadiaMono;src:url(/static/woff2/CascadiaMono-Italic.woff2);font-style:italic}</style><link rel=stylesheet href=/static/css/bootstrap-icons.min.css></link>
2
- <link href=/static/css/bootstrap.min.css rel=stylesheet crossorigin=anonymous></link><style>html{height:100%;width:100%;position:fixed}body{height:100%;margin:0;overflow:hidden}body>:first-child{height:100%}#runtimepy{height:100%}#runtimepy-tabs{width:min-content}#runtimepy-splash{position:fixed;top:0;left:0;width:100vw;height:100vh;opacity:1}.click-plot{cursor:pointer}.stale{color:var(--bs-warning-text-emphasis)!important}.slider{min-width:8em}.toggle-value{}.window-button{border-right:var(--bs-border-width)var(--bs-border-style)var(--bs-link-hover-color)!important}canvas:focus{outline:none}.flex-column-scroll-bodge{height:100%;flex-wrap:nowrap;overflow-y:scroll;flex-shrink:0}.scroll{overflow:scroll}.tab-content-bodge{width:100%;height:100%}.button-bodge{text-align:left}.collapsing{transition:none!important}.tab-pane.fade{transition:none!important}.modal.fade{transition:none!important}.modal-dialog{width:80%;max-width:80%}.table{margin-bottom:0;width:auto}.table-container{overflow-x:scroll;min-height:fit-content}.channel-column{overflow-y:scroll;overflow-x:hidden;flex-grow:0;flex-shrink:0;max-width:75%}.channel-value{min-width:10em}.table>tbody>tr>td{vertical-align:middle}.collapse:not(.show){display:none!important}select.form-select{width:min-content}select.form-select:hover{cursor:pointer}textarea.text-logs{min-height:10em!important;padding-top:0!important;padding-bottom:0!important;border-top:0}.vertical-divider{flex-basis:.75em;flex-grow:0;flex-shrink:0}pre{color:var(--bs-code-color)}.vertical-divider:hover{cursor:col-resize;background-color:var(--bs-highlight-bg)!important}button:hover{background-color:var(--bs-tertiary-bg)}.channel-value-input{width:6em}:root,[data-bs-theme=dark],[data-bs-theme=light]{--bs-font-sans-serif:CascadiaCode, system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", "Liberation Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";--bs-font-monospace:CascadiaMono, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace}</style><div id=runtimepy class="align-items-start d-flex bg-body" data-bs-theme=dark><div class="d-flex h-100 bg-dark-subtle flex-column"><button type=button id=theme-button class="btn btn-secondary rounded-0 font-monospace button-bodge text-nowrap has-tooltip" data-bs-title=" Toggle light/dark." data-bs-placement=right>
1
+ <!doctype html><html lang=en><meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1"><title>Libre Embedded - Home
2
+ </title><meta http-equiv=Cache-Control content="public"><link rel=icon href=/favicon.ico><meta name=description content="Libre Embedded Engineering Technologies LLC is an engineering consultancy and product development company. This page was rendered from Markdown by runtimepy/5.13.3."><style>@font-face{font-family:CascadiaCode;src:url(/static/woff2/CascadiaCode-Regular.woff2)}@font-face{font-family:CascadiaCode;src:url(/static/woff2/CascadiaCode-Bold.woff2);font-weight:700}@font-face{font-family:CascadiaCode;src:url(/static/woff2/CascadiaCode-BoldItalic.woff2);font-weight:700;font-style:italic}@font-face{font-family:CascadiaCode;src:url(/static/woff2/CascadiaCode-Italic.woff2);font-style:italic}@font-face{font-family:CascadiaMono;src:url(/static/woff2/CascadiaMono-Regular.woff2)}@font-face{font-family:CascadiaMono;src:url(/static/woff2/CascadiaMono-Bold.woff2);font-weight:700}@font-face{font-family:CascadiaMono;src:url(/static/woff2/CascadiaMono-BoldItalic.woff2);font-weight:700;font-style:italic}@font-face{font-family:CascadiaMono;src:url(/static/woff2/CascadiaMono-Italic.woff2);font-style:italic}</style><link rel=stylesheet href=/static/css/bootstrap-icons.min.css></link>
3
+ <link href=/static/css/bootstrap.min.css rel=stylesheet crossorigin=anonymous></link><style>html{height:100%;width:100%;position:fixed}body{height:100%;margin:0;overflow:hidden}body>:first-child{height:100%}#runtimepy{height:100%}#runtimepy-tabs{width:min-content}#runtimepy-splash{position:fixed;top:0;left:0;width:100vw;height:100vh;opacity:1}.click-plot{cursor:pointer}.stale{color:var(--bs-warning-text-emphasis)!important}.slider{min-width:8em}.toggle-value{}.window-button{border-right:var(--bs-border-width)var(--bs-border-style)var(--bs-link-hover-color)!important}:focus{outline:none}.flex-column-scroll-bodge{height:100%;flex-wrap:nowrap;overflow-y:scroll;flex-shrink:0}.scroll{overflow:scroll}.tab-content-bodge{width:100%;height:100%}.button-bodge{text-align:left}.collapsing{transition:none!important}.tab-pane.fade{transition:none!important}.modal.fade{transition:none!important}.modal-dialog{width:80%;max-width:80%}.table{margin-bottom:0;width:auto}.table-container{overflow-x:scroll;min-height:fit-content}.channel-column{overflow-y:scroll;overflow-x:hidden;flex-grow:0;flex-shrink:0;max-width:75%}.channel-value{min-width:10em}.table>tbody>tr>td{vertical-align:middle}.collapse:not(.show){display:none!important}select.form-select{width:min-content}select.form-select:hover{cursor:pointer}textarea.text-logs{min-height:10em!important;padding-top:0!important;padding-bottom:0!important;border-top:0}.vertical-divider{flex-basis:.75em;flex-grow:0;flex-shrink:0}pre{color:var(--bs-code-color)}.vertical-divider:hover{cursor:col-resize;background-color:var(--bs-highlight-bg)!important}button:hover{background-color:var(--bs-tertiary-bg)}.channel-value-input{width:6em}:root,[data-bs-theme=dark],[data-bs-theme=light]{--bs-font-sans-serif:CascadiaCode, system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", "Liberation Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";--bs-font-monospace:CascadiaMono, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace}</style><div id=runtimepy class="d-flex bg-body align-items-start" data-bs-theme=dark><div class="bg-dark-subtle d-flex h-100 flex-column"><button type=button id=theme-button title="change theme button" class="btn btn-secondary rounded-0 font-monospace button-bodge text-nowrap has-tooltip" data-bs-title="Toggle light/dark." data-bs-placement=right>
3
4
  <i class="bi bi-lightbulb"></i>
4
5
  </button>
5
- <a href="?print=true"><button type=button id=print-button class="btn btn-secondary rounded-0 font-monospace button-bodge text-nowrap has-tooltip" data-bs-title="Printer-friendly view." data-bs-placement=right>
6
- <i class="bi bi-printer"></i></button></a></div><div class="d-flex h-100 justify-content-between flex-grow-1 flex-column overflow-y-auto text-body"><div></div><div class="d-flex flex-row justify-content-between"><div></div><div class="text-body p-3 pb-0"><h1><a href=/><img alt=logo src=/static/png/chip-circle-bootstrap/128x128.png></a> Resource Not Found (404) <a href=/><img alt=logo src=/static/png/chip-circle-bootstrap/128x128.png></a></h1><p>(<a href=/>home</a>)</div><div></div></div><div></div></div></div><script>function worker_config(e){let t={},s="runtimepy_websocket",n="ws";location.protocol.includes("https")&&(s="runtimepy_secure_websocket",n+="s");let o=e.config.ports;for(let r in o){let i=o[r],a=e.config.websocket_hostname||window.location.hostname;i.name.includes(s)&&(i.name.includes("data")?t.data=`${n}://${a}:`+i.port:t.json=`${n}://${a}:`+i.port)}return t}let tabFilter=void 0;function bootstrap_init(){const t=document.querySelectorAll(".has-tooltip"),n=[...t].map(e=>new bootstrap.Tooltip(e));let e=document.getElementById("runtimepy-tabs");e&&(tabFilter=new TabFilter(e))}let lightMode=!1;function lightDarkClick(){lightMode=!lightMode,document.getElementById("runtimepy").setAttribute("data-bs-theme",lightMode?"light":"dark"),window.location.hash=lightMode?"#light-mode":""}window.onload=()=>{let e=document.getElementById("theme-button");if(e&&e.addEventListener("click",lightDarkClick),window.location.hash){let t=window.location.hash.slice(1).split(",");t.includes("light-mode")&&e.click()}bootstrap_init()}</script><script src=/static/js/bootstrap.bundle.min.js crossorigin=anonymous></script>
6
+ <a href="?print=true"><button type=button id=print-button title="print-view button" class="btn btn-secondary rounded-0 font-monospace button-bodge text-nowrap has-tooltip" data-bs-title="Printer-friendly view." data-bs-placement=right>
7
+ <i class="bi bi-printer"></i></button></a></div><div class="h-100 flex-grow-1 justify-content-between text-body d-flex overflow-y-auto flex-column"><div></div><div class="justify-content-between d-flex flex-row"><div></div><div class="text-body p-3 pb-0"><h1><a href=/><img alt=logo src=/static/png/chip-circle-bootstrap/128x128.png></a> Resource Not Found (404) <a href=/><img alt=logo src=/static/png/chip-circle-bootstrap/128x128.png></a></h1><p>(<a href=/>home</a>)</div><div></div></div><div></div></div></div><script>function worker_config(e){let t={},s="runtimepy_websocket",n="ws";location.protocol.includes("https")&&(s="runtimepy_secure_websocket",n+="s");let o=e.config.ports;for(let r in o){let i=o[r],a=e.config.websocket_hostname||window.location.hostname;i.name.includes(s)&&(i.name.includes("data")?t.data=`${n}://${a}:`+i.port:t.json=`${n}://${a}:`+i.port)}return t}let tabFilter=void 0;function bootstrap_init(){const t=document.querySelectorAll(".has-tooltip"),n=[...t].map(e=>new bootstrap.Tooltip(e));let e=document.getElementById("runtimepy-tabs");e&&(tabFilter=new TabFilter(e))}let lightMode=!1;function lightDarkClick(){lightMode=!lightMode,document.getElementById("runtimepy").setAttribute("data-bs-theme",lightMode?"light":"dark"),window.location.hash=lightMode?"#light-mode":""}window.onload=()=>{let e=document.getElementById("theme-button");if(e&&e.addEventListener("click",lightDarkClick),window.location.hash){let t=window.location.hash.slice(1).split(",");t.includes("light-mode")&&e.click()}bootstrap_init()}</script><script src=/static/js/bootstrap.bundle.min.js crossorigin=anonymous></script>
@@ -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"}
@@ -88,6 +88,13 @@ class ResponseHeader(HeadersMixin):
88
88
  self.headers,
89
89
  )
90
90
 
91
+ def static_resource(
92
+ self, value: str = "public, max-age=31536000, immutable"
93
+ ) -> None:
94
+ """Set headers for static resources."""
95
+
96
+ self["Cache-Control"] = value
97
+
91
98
 
92
99
  class AsyncResponse:
93
100
  """
@@ -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(
@@ -222,6 +237,8 @@ class RuntimepyServerConnection(HttpConnection):
222
237
 
223
238
  self.logger.info("Serving '%s' (MIME: %s)", candidate, mime)
224
239
 
240
+ response.static_resource()
241
+
225
242
  # Return the file data.
226
243
  result = AsyncResponse(candidate)
227
244
  break
@@ -306,6 +323,7 @@ class RuntimepyServerConnection(HttpConnection):
306
323
  # Handle favicon (for browser clients).
307
324
  if path.startswith("/favicon"):
308
325
  response["Content-Type"] = "image/x-icon"
326
+ response.static_resource()
309
327
  return self.favicon_data
310
328
 
311
329
  # Try serving a file and handling redirects.
@@ -336,6 +354,7 @@ class RuntimepyServerConnection(HttpConnection):
336
354
  response,
337
355
  request_data,
338
356
  default_app=type(self).default_app,
357
+ **type(self).metadata,
339
358
  )
340
359
 
341
360
  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
 
@@ -65,6 +68,12 @@ class HttpConnection(_TcpConnection):
65
68
  # runtime don't need additional initialization.
66
69
  handlers: HttpRequestHandlers = {}
67
70
 
71
+ headers: dict[str, str] = {
72
+ "Server": PKG_NAME,
73
+ "X-Content-Type-Options": "nosniff",
74
+ "Cache-Control": "public",
75
+ }
76
+
68
77
  def init(self) -> None:
69
78
  """Initialize this instance."""
70
79
 
@@ -125,12 +134,9 @@ class HttpConnection(_TcpConnection):
125
134
  f"No handler for {request_header.method} requests."
126
135
  )
127
136
 
128
- # Set boilerplate header data.
129
-
130
- # webhint suggestions
131
- # response["server"] = self.identity
132
- response["server"] = PKG_NAME
133
- response["X-Content-Type-Options"] = "nosniff"
137
+ for key, value in type(self).headers.items():
138
+ if response.get(key) is None:
139
+ response[key] = value
134
140
 
135
141
  return result
136
142
 
@@ -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.3
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
24
21
  Requires-Dist: psutil
22
+ Requires-Dist: vcorelib>=3.5.8
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=7dce65a7ea83c118cf5fa28ddbfd533f
55
55
  =====================================
56
56
  -->
57
57
 
58
- # runtimepy ([5.13.1](https://pypi.org/project/runtimepy/))
58
+ # runtimepy ([5.13.3](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=PA875n9FnR5SNQeBAYDidfPF2YLu8Bfzfy0FmQ0KMs8,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
@@ -41,14 +41,15 @@ runtimepy/control/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU
41
41
  runtimepy/control/source.py,sha256=nW3Q2D-LcekII7K5XKbxXCcR-9jYQyvv0UypeNy1Dnw,1695
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
- runtimepy/data/404.html,sha256=D_nhuj1AfO5EaIVsajknfaeZ5cVDKCNRPtUY4MHg1Xc,5326
44
+ runtimepy/data/404.html,sha256=c_cIqG5BxcKw7pDHcgAAPeOdQq1JRAWIBZ331tG9LKw,5673
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
@@ -190,14 +191,14 @@ runtimepy/net/http/__init__.py,sha256=4TjFp_ajAVcOEvwtjlF6mG-9EbEePqFZht-QpWIKVB
190
191
  runtimepy/net/http/common.py,sha256=vpoO6XwRmrZmTkCu9bkI0HnyaD8MWTpV7ADesCNrfRE,2237
191
192
  runtimepy/net/http/header.py,sha256=AECSdvhBA9_5Pg3UdwMzsmBpcqgsiPj41xnIGPm5g5E,2296
192
193
  runtimepy/net/http/request_target.py,sha256=EE1aI5VSARw1h93jyZvP56ir5O5fjd6orYK-1FM4JNk,1550
193
- runtimepy/net/http/response.py,sha256=y33KLUJNE7zx6biUMwTkUfQ1bXiKV6pjrcxuh8U3WCE,3216
194
+ runtimepy/net/http/response.py,sha256=fD0R_BUgmNwdwKQtXvYfTYM7DyJlwsGmlNVi5HkCOhU,3409
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=prEf7pNhM7t9xP7_ZM0uzESUomlZuqDtDlE34MnyCb0,11431
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=-ODo-dJcyD-NZnRIFoWT9JdQnDaP_cXJ9IViwXIQe24,6301
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.3.dist-info/licenses/LICENSE,sha256=yKBRwbO-cOPBrlpsZmJkkSa33DfY31aE8t7lZ0DwlUo,1071
305
+ runtimepy-5.13.3.dist-info/METADATA,sha256=Uhk1dl_ko8_-Odbf4SHfTDplaCbM6CP5R9S4TYS9jK0,9269
306
+ runtimepy-5.13.3.dist-info/WHEEL,sha256=0CuiUZ_p9E4cD6NyLD6UG80LBXYyiSYZOKDm5lp32xk,91
307
+ runtimepy-5.13.3.dist-info/entry_points.txt,sha256=-btVBkYv7ybcopqZ_pRky-bEzu3vhbaG3W3Z7ERBiFE,51
308
+ runtimepy-5.13.3.dist-info/top_level.txt,sha256=0jPmh6yqHyyJJDwEID-LpQly-9kQ3WRMjH7Lix8peLg,10
309
+ runtimepy-5.13.3.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