runtimepy 5.7.5__py3-none-any.whl → 5.7.6__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.1.4
4
- # hash=3797b5155c13d8d7422bdbfcb1248cca
4
+ # hash=cab7cff2cb194a61178fa386b80eae85
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.7.5"
13
+ VERSION = "5.7.6"
14
14
 
15
15
  # runtimepy-specific content.
16
16
  METRICS_NAME = "metrics"
@@ -0,0 +1,3 @@
1
+ <html lang=en><meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1"><title>runtimepy/5.7.6</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=https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css></link>
2
+ <link href=https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css rel=stylesheet crossorigin=anonymous></link><style>html{height:100%}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}.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}.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 bg-body d-flex" data-bs-theme=dark><div class="bg-dark-subtle h-100 d-flex 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>
3
+ <i class="bi bi-lightbulb"></i></button></div><div class="overflow-y-auto d-flex flex-grow-1 h-100 flex-column justify-content-between 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=https://libre-embedded.com><img alt=logo src=https://libre-embedded.com/static/png/chip-circle-bootstrap/128x128.png></a> Resource Not Found (404) <a href=https://libre-embedded.com><img alt=logo src=https://libre-embedded.com/static/png/chip-circle-bootstrap/128x128.png></a></h1><p>(<a href=https://libre-embedded.com>home</a>)</div><div></div></div><div></div></div></div><script>let lightMode=!1;function lightDarkClick(){lightMode=!lightMode,document.getElementById("runtimepy").setAttribute("data-bs-theme",lightMode?"light":"dark"),window.location.hash=lightMode?"#light-mode":""}let lightDarkButton=document.getElementById("theme-button");if(lightDarkButton&&lightDarkButton.addEventListener("click",lightDarkClick),window.location.hash){let e=window.location.hash.slice(1).split(",");e.includes("light-mode")&&lightDarkButton.click()}</script><script src=https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js crossorigin=anonymous></script>
@@ -13,11 +13,23 @@ structs:
13
13
  init:
14
14
  - runtimepy.net.arbiter.housekeeping.init
15
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
+
16
29
  servers:
17
30
  - factory: runtimepy_http
18
31
  kwargs: {port: "$runtimepy_http_server"}
19
-
20
32
  - factory: runtimepy_websocket_json
21
- kwargs: {host: "0.0.0.0", port: "$runtimepy_websocket_json_server"}
33
+ kwargs: {port: "$runtimepy_websocket_json_server"}
22
34
  - factory: runtimepy_websocket_data
23
- kwargs: {host: "0.0.0.0", port: "$runtimepy_websocket_data_server"}
35
+ kwargs: {port: "$runtimepy_websocket_data_server"}
@@ -0,0 +1,32 @@
1
+ """
2
+ A module implementing connection-arbiter related utilities.
3
+ """
4
+
5
+ # internal
6
+ from runtimepy.net.arbiter.config import ConfigObject
7
+
8
+
9
+ def web_app_paths(config: ConfigObject) -> None:
10
+ """
11
+ Register boilerplate path handling for additional application-serving URIs.
12
+ """
13
+
14
+ config.setdefault("config", {})
15
+ redirects = config["config"].setdefault("http_redirects", {})
16
+ app_paths = config["config"].setdefault("http_app_paths", [])
17
+
18
+ for prefix in config["config"].get("http_app_prefixes", []):
19
+ if not prefix.startswith("/"):
20
+ prefix = "/" + prefix
21
+
22
+ assert not prefix.endswith("/"), prefix
23
+
24
+ # Add re-directs.
25
+ index_path = f"{prefix}/index.html"
26
+ app_path = f"{prefix}/app.html"
27
+ redirects.setdefault(prefix, index_path)
28
+ redirects.setdefault(index_path, app_path)
29
+
30
+ # Add app path.
31
+ if app_path not in app_paths:
32
+ app_paths.append(app_path)
@@ -109,6 +109,18 @@ class RuntimepyServerConnection(HttpConnection):
109
109
  with favicon.open("rb") as favicon_fd:
110
110
  type(self).favicon_data = favicon_fd.read()
111
111
 
112
+ def redirect_to(
113
+ self,
114
+ path: str,
115
+ response: ResponseHeader,
116
+ status: http.HTTPStatus = http.HTTPStatus.TEMPORARY_REDIRECT,
117
+ ) -> bytes:
118
+ """Handle responding with redirection status."""
119
+
120
+ response["Location"] = path
121
+ response.status = status
122
+ return bytes()
123
+
112
124
  async def try_redirect(
113
125
  self, path: PathMaybeQuery, response: ResponseHeader
114
126
  ) -> Optional[bytes]:
@@ -118,33 +130,39 @@ class RuntimepyServerConnection(HttpConnection):
118
130
 
119
131
  curr = Path(path[0])
120
132
  if curr in self.class_redirect_paths:
121
- response["Location"] = str(self.class_redirect_paths[curr])
122
- response.status = http.HTTPStatus.TEMPORARY_REDIRECT
123
-
124
- # No data payload, but signal to caller that a response is ready.
125
- result = bytes()
133
+ result = self.redirect_to(
134
+ str(self.class_redirect_paths[curr]), response
135
+ )
126
136
 
127
137
  return result
128
138
 
129
- async def render_markdown(
130
- self, path: Path, response: ResponseHeader, **kwargs
139
+ def render_markdown(
140
+ self, content: str, response: ResponseHeader, **kwargs
131
141
  ) -> bytes:
132
- """Render a markdown file as HTML and return the result."""
142
+ """Return rendered markdown content."""
133
143
 
134
144
  document = get_html()
135
-
136
- async with aiofiles.open(path, mode="r") as path_fd:
137
- with IndentedFileWriter.string() as writer:
138
- writer.write_markdown(await path_fd.read(), **kwargs)
139
- full_markdown_page(
140
- document,
141
- writer.stream.getvalue(), # type: ignore
142
- )
145
+ with IndentedFileWriter.string() as writer:
146
+ writer.write_markdown(content, **kwargs)
147
+ full_markdown_page(
148
+ document,
149
+ writer.stream.getvalue(), # type: ignore
150
+ )
143
151
 
144
152
  response["Content-Type"] = f"text/html; charset={DEFAULT_ENCODING}"
145
153
 
146
154
  return document.encode_str().encode()
147
155
 
156
+ async def render_markdown_file(
157
+ self, path: Path, response: ResponseHeader, **kwargs
158
+ ) -> bytes:
159
+ """Render a markdown file as HTML and return the result."""
160
+
161
+ async with aiofiles.open(path, mode="r") as path_fd:
162
+ return self.render_markdown(
163
+ await path_fd.read(), response, **kwargs
164
+ )
165
+
148
166
  async def try_file(
149
167
  self, path: PathMaybeQuery, response: ResponseHeader
150
168
  ) -> Optional[bytes]:
@@ -157,9 +175,12 @@ class RuntimepyServerConnection(HttpConnection):
157
175
  candidate = search.joinpath(path[0][1:])
158
176
 
159
177
  # Handle markdown sources.
160
- md_candidate = candidate.with_suffix(".md")
161
- if md_candidate.is_file():
162
- return await self.render_markdown(md_candidate, response)
178
+ if candidate.name:
179
+ md_candidate = candidate.with_suffix(".md")
180
+ if md_candidate.is_file():
181
+ return await self.render_markdown_file(
182
+ md_candidate, response
183
+ )
163
184
 
164
185
  if candidate.is_file():
165
186
  mime, encoding = mimetypes.guess_type(candidate, strict=False)
@@ -239,6 +260,7 @@ class RuntimepyServerConnection(HttpConnection):
239
260
  request.log(self.logger, False, level=logging.INFO)
240
261
 
241
262
  result = None
263
+ populated = False
242
264
 
243
265
  with StringIO() as stream:
244
266
  if request.target.origin_form:
@@ -250,7 +272,7 @@ class RuntimepyServerConnection(HttpConnection):
250
272
  return self.favicon_data
251
273
 
252
274
  # Try serving a file and handling redirects.
253
- for handler in [self.try_redirect, self.try_file]:
275
+ for handler in [self.try_file, self.try_redirect]:
254
276
  result = await handler(
255
277
  request.target.origin_form, response
256
278
  )
@@ -266,10 +288,11 @@ class RuntimepyServerConnection(HttpConnection):
266
288
  request_data,
267
289
  self.json_data,
268
290
  )
291
+ populated = True
269
292
 
270
293
  # Serve the application.
271
294
  else:
272
- await html_handler(
295
+ populated = await html_handler(
273
296
  type(self).apps,
274
297
  stream,
275
298
  request,
@@ -278,6 +301,7 @@ class RuntimepyServerConnection(HttpConnection):
278
301
  default_app=type(self).default_app,
279
302
  )
280
303
 
281
- result = stream.getvalue().encode()
304
+ if populated:
305
+ result = stream.getvalue().encode()
282
306
 
283
- return result
307
+ return result or self.redirect_to("/404.html", response)
@@ -69,9 +69,10 @@ async def setup(app: AppInfo) -> int:
69
69
  )
70
70
 
71
71
  # Default application (environment tabs).
72
- web_app = create_app(app, getattr(_import_module(module), method))
73
- RuntimepyServerConnection.apps["/app.html"] = web_app
74
- RuntimepyServerConnection.default_app = web_app
72
+ html_app = create_app(app, getattr(_import_module(module), method))
73
+ target: str
74
+ for target in app.config_param("http_app_paths", []):
75
+ RuntimepyServerConnection.apps[target] = html_app
75
76
 
76
77
  # Register redirects.
77
78
  redirects: dict[str, str] = app.config_param("http_redirects", {})
@@ -33,7 +33,7 @@ async def html_handler(
33
33
  response: ResponseHeader,
34
34
  request_data: Optional[bytes],
35
35
  default_app: HtmlApp = None,
36
- ) -> None:
36
+ ) -> bool:
37
37
  """Render an HTML document in response to an HTTP request."""
38
38
 
39
39
  # Set response headers.
@@ -43,3 +43,5 @@ async def html_handler(
43
43
  app = apps.get(request.target.path, default_app)
44
44
  if app is not None:
45
45
  (await app(get_html(), request, response, request_data)).render(stream)
46
+
47
+ return app is not None
@@ -219,6 +219,7 @@ class TcpConnection(_Connection, _TransportMixin):
219
219
  peer: type[V] = None,
220
220
  serve_kwargs: dict[str, _Any] = None,
221
221
  connect_kwargs: dict[str, _Any] = None,
222
+ host: str = "127.0.0.1",
222
223
  ) -> _AsyncIterator[tuple[V, T]]:
223
224
  """Create a connection pair."""
224
225
 
@@ -241,16 +242,22 @@ class TcpConnection(_Connection, _TransportMixin):
241
242
  serve_kwargs = {}
242
243
 
243
244
  server = await stack.enter_async_context(
244
- peer.serve(callback, port=0, backlog=1, **serve_kwargs)
245
+ peer.serve(
246
+ callback,
247
+ host=host,
248
+ port=0,
249
+ backlog=1,
250
+ **serve_kwargs,
251
+ )
245
252
  )
246
253
 
247
- host = server.sockets[0].getsockname()
248
-
249
254
  if connect_kwargs is None:
250
255
  connect_kwargs = {}
251
256
 
252
257
  client = await cls.create_connection(
253
- host="localhost", port=host[1], **connect_kwargs
258
+ host=host,
259
+ port=server.sockets[0].getsockname()[1],
260
+ **connect_kwargs,
254
261
  )
255
262
  await cond.acquire()
256
263
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: runtimepy
3
- Version: 5.7.5
3
+ Version: 5.7.6
4
4
  Summary: A framework for implementing Python services.
5
5
  Home-page: https://github.com/vkottler/runtimepy
6
6
  Author: Vaughn Kottler
@@ -17,11 +17,11 @@ 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
20
  Requires-Dist: aiofiles
22
- Requires-Dist: psutil
23
21
  Requires-Dist: websockets
24
22
  Requires-Dist: vcorelib >=3.4.2
23
+ Requires-Dist: psutil
24
+ Requires-Dist: svgen >=0.6.8
25
25
  Provides-Extra: test
26
26
  Requires-Dist: pylint ; extra == 'test'
27
27
  Requires-Dist: flake8 ; extra == 'test'
@@ -45,11 +45,11 @@ Requires-Dist: uvloop ; (sys_platform != "win32" and sys_platform != "cygwin") a
45
45
  =====================================
46
46
  generator=datazen
47
47
  version=3.1.4
48
- hash=c982a40a3245e84b1ae3b70a17cc6867
48
+ hash=41ff8742602f69f2831092a4b666cddc
49
49
  =====================================
50
50
  -->
51
51
 
52
- # runtimepy ([5.7.5](https://pypi.org/project/runtimepy/))
52
+ # runtimepy ([5.7.6](https://pypi.org/project/runtimepy/))
53
53
 
54
54
  [![python](https://img.shields.io/pypi/pyversions/runtimepy.svg)](https://pypi.org/project/runtimepy/)
55
55
  ![Build Status](https://github.com/vkottler/runtimepy/workflows/Python%20Package/badge.svg)
@@ -1,4 +1,4 @@
1
- runtimepy/__init__.py,sha256=HLqHKus27mAm-Nh_U5EdrCf_R2nhaeE0mZjKU31G_sI,390
1
+ runtimepy/__init__.py,sha256=47z6hCc2pWcbeYdGuB007x_wR84imlspZBFz0Ue3_oc,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
@@ -41,13 +41,14 @@ 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=sn0Mcntzb1-AekukYZAQqz43xfmZtTWa2n2HD2ItqDM,4697
44
45
  runtimepy/data/browser.yaml,sha256=oc5KEV1C1uAJ4MkhNo4hyVVfJtZvHelRNqzNvD313Ow,79
45
46
  runtimepy/data/dummy_load.yaml,sha256=89BPHLaHJOgiiZSVACBA0_xmlN_N6v2fpcCauB03ZkE,1830
46
47
  runtimepy/data/factories.yaml,sha256=Jm0QPwW2BQgnj1fIFQwygsWXzT78QJuf7auVRtRzWKQ,1847
47
48
  runtimepy/data/favicon.ico,sha256=iPOtqnqrFVr5tNBM6kTsw7nh0KullEz4TpS6CEQ2HVM,362870
48
49
  runtimepy/data/sample_telemetry.yaml,sha256=OpdFurkvtWJGaNl9LMlU2rKo15AaVVr-U_hoZfsbp-Y,695
49
50
  runtimepy/data/server.yaml,sha256=wS_Ceiu2TpkfPurpqoYoPlgzc9DAWtUd24MW7t-S5rU,97
50
- runtimepy/data/server_base.yaml,sha256=QkF1xcHyMEViUhOc5rKFbFXjbRDDDHbX5LXvSQJRS58,615
51
+ runtimepy/data/server_base.yaml,sha256=R_varVgGPGV4nxWYYwKUnHC9ufINi4V92YVhxCCC5wg,875
51
52
  runtimepy/data/server_dev.yaml,sha256=nQsPh7LuQig3pzHfdg_aD3yOUiCj1sKKfI-WwW3hXmQ,523
52
53
  runtimepy/data/tftp_server.yaml,sha256=-bFOWJSagI-fEQQcT8k7eDMJVfSPm2XAxLVG3dqUTa4,204
53
54
  runtimepy/data/css/bootstrap_extra.css,sha256=-clAoiYcyOkS4xana4O-jvGVsphOaYB_VlmX9mUjI80,1796
@@ -166,6 +167,7 @@ runtimepy/net/arbiter/tcp/__init__.py,sha256=djNm8il_9aLNpGsYResJlFmyIqx9XNLqVay
166
167
  runtimepy/net/arbiter/tcp/json.py,sha256=W9a_OwBPmIoB2XZf4iuAIWQhMg2qA9xejBhGBdNCPnI,742
167
168
  runtimepy/net/factories/__init__.py,sha256=rPdBVpgzzQYF61w6efQrEre71yMPHd6kanBpMdOX-3c,4672
168
169
  runtimepy/net/html/__init__.py,sha256=BQeGpZWfGSmMg1R0N9GaOZfyFn4UQGHKoFOhd-1G75Q,3983
170
+ runtimepy/net/html/arbiter.py,sha256=SkZZm-CmyCxbAcWZbvCLH-RwFUJPvrvR5yWysVVuvCM,951
169
171
  runtimepy/net/html/bootstrap/__init__.py,sha256=ONhwx68piWjsrf88FMpda84TWSPqgi-RZCBuWCci_ak,1444
170
172
  runtimepy/net/html/bootstrap/elements.py,sha256=8sq79EPR8TF9oYV_4I0Sba_PikHOpEaxUvQ7bqtm0ow,4800
171
173
  runtimepy/net/html/bootstrap/tabs.py,sha256=7-0lJOD9SALmsViUYGJAXF0PTSqtffc4mpoFwmYcnXE,3842
@@ -176,10 +178,10 @@ runtimepy/net/http/request_target.py,sha256=EE1aI5VSARw1h93jyZvP56ir5O5fjd6orYK-
176
178
  runtimepy/net/http/response.py,sha256=Sup8W_A0ADNzR5olKrQsVNhsQXUwPOD-eJLlLOgYlAY,2316
177
179
  runtimepy/net/http/state.py,sha256=qCMN8aWfCRfU9XP-cIhSOo2RqfljTjbQRCflfcy2bfY,1626
178
180
  runtimepy/net/http/version.py,sha256=mp6rgIM7-VUVKLCA0Uw96CmBkL0ET860lDVVEewpZ7w,1098
179
- runtimepy/net/server/__init__.py,sha256=Yt2ltmiQDkVNjvYCqFh1kHlK0eelWYVHwQNkJxozta0,8946
180
- runtimepy/net/server/html.py,sha256=dlVqIEDTdAhU7NK84sTqXqGxHpqndsWS36Kgzy9MJdE,1189
181
+ runtimepy/net/server/__init__.py,sha256=ZsJGvak5OPHyuGPDThwj9roOj8ZcwqrOrzTD27hJhCo,9621
182
+ runtimepy/net/server/html.py,sha256=ufg0PQF_iUE7PT0n3Pn3jTcun7mspZUI6_ooblcNnvI,1217
181
183
  runtimepy/net/server/json.py,sha256=a7vM5yfq2er4DexzFqEMnxoMGDeuywKkVH4-uNJBAik,2522
182
- runtimepy/net/server/app/__init__.py,sha256=Q5NWlAkIZE2oEHkGdILFyQoX1Fw1lMR1lVQyMVkJ_Hc,2989
184
+ runtimepy/net/server/app/__init__.py,sha256=beU67t7zoKGlO7aldjQMUwYLm9mSlc78eMQazri-otw,3012
183
185
  runtimepy/net/server/app/base.py,sha256=HF_Qa3ufrZNaYBVnBwGi-Siv3nneqEo01j5h5pK-ZTk,1871
184
186
  runtimepy/net/server/app/create.py,sha256=eRT8qxubht5A7149Xol3Z8rkdYd_pjNLqrlyMnXk-Zg,2660
185
187
  runtimepy/net/server/app/elements.py,sha256=KJt9vWqkfvniJMiLOJN467JjPPrEqJYZXmDuY1JoY1g,455
@@ -206,7 +208,7 @@ runtimepy/net/stream/base.py,sha256=Dg4vcR0n9y2122AyJ-9W-jkEhNla_EHO-DqJJPfGD4k,
206
208
  runtimepy/net/stream/string.py,sha256=61mgserU3p6j5gAcK0oe0aKqL6vDh7NtgJvbPoiAUPM,784
207
209
  runtimepy/net/stream/json/__init__.py,sha256=h--C_9moW92TC_e097FRRXcg8GJ6VVbMLXl1cICknys,2508
208
210
  runtimepy/net/tcp/__init__.py,sha256=OOWohegpoioSTf8M7uDf-4EV1IDungz7-U19L_2yW4I,250
209
- runtimepy/net/tcp/connection.py,sha256=WNc8n3rtH7xBrX6r7pyNfQiNpPasO2WuhjxWQrqvwHg,8647
211
+ runtimepy/net/tcp/connection.py,sha256=sYWj2aDiAHQf70zfRJM24cHraFd_TuzTD4fRWeSQZXE,8811
210
212
  runtimepy/net/tcp/create.py,sha256=zZsRs5KYpO3bNGh-DwEOEzjUDE4ixj-UBHYgZ0GvC7c,2013
211
213
  runtimepy/net/tcp/protocol.py,sha256=vEnIX3gUX2nrw9ofT_e4KYU4VY2k4WP0WuOi4eE_OOQ,1444
212
214
  runtimepy/net/tcp/http/__init__.py,sha256=BY9ra0s7kHkoUQKIRHsnk3_WDWP7Xt-FxQ90K14nwkc,5737
@@ -282,9 +284,9 @@ runtimepy/tui/task.py,sha256=nUZo9fuOC-k1Wpqdzkv9v1tQirCI28fZVgcC13Ijvus,1093
282
284
  runtimepy/tui/channels/__init__.py,sha256=evDaiIn-YS9uGhdo8ZGtP9VK1ek6sr_P1nJ9JuSET0o,4536
283
285
  runtimepy/ui/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
284
286
  runtimepy/ui/controls.py,sha256=yvT7h3thbYaitsakcIAJ90EwKzJ4b-jnc6p3UuVf_XE,1241
285
- runtimepy-5.7.5.dist-info/LICENSE,sha256=okYCYhGsx_BlzvFdoNVBVpw_Cfb4SOqHA_VAARml4Hc,1071
286
- runtimepy-5.7.5.dist-info/METADATA,sha256=ZQHQx1_ZZwhmeLWJGLbkjXBevAIdSdQ0h__PaynAdDA,9308
287
- runtimepy-5.7.5.dist-info/WHEEL,sha256=OVMc5UfuAQiSplgO0_WdW7vXVGAt9Hdd6qtN4HotdyA,91
288
- runtimepy-5.7.5.dist-info/entry_points.txt,sha256=-btVBkYv7ybcopqZ_pRky-bEzu3vhbaG3W3Z7ERBiFE,51
289
- runtimepy-5.7.5.dist-info/top_level.txt,sha256=0jPmh6yqHyyJJDwEID-LpQly-9kQ3WRMjH7Lix8peLg,10
290
- runtimepy-5.7.5.dist-info/RECORD,,
287
+ runtimepy-5.7.6.dist-info/LICENSE,sha256=okYCYhGsx_BlzvFdoNVBVpw_Cfb4SOqHA_VAARml4Hc,1071
288
+ runtimepy-5.7.6.dist-info/METADATA,sha256=p5qI1xHfkh1RGygCvs5SsLxk4NzECG15G_5699VRsl8,9308
289
+ runtimepy-5.7.6.dist-info/WHEEL,sha256=OVMc5UfuAQiSplgO0_WdW7vXVGAt9Hdd6qtN4HotdyA,91
290
+ runtimepy-5.7.6.dist-info/entry_points.txt,sha256=-btVBkYv7ybcopqZ_pRky-bEzu3vhbaG3W3Z7ERBiFE,51
291
+ runtimepy-5.7.6.dist-info/top_level.txt,sha256=0jPmh6yqHyyJJDwEID-LpQly-9kQ3WRMjH7Lix8peLg,10
292
+ runtimepy-5.7.6.dist-info/RECORD,,