runtimepy 5.7.2__py3-none-any.whl → 5.7.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/data/js/markdown_page.js +24 -0
- runtimepy/mixins/logging.py +26 -3
- runtimepy/net/html/__init__.py +163 -0
- runtimepy/net/{server/app → html}/bootstrap/elements.py +4 -2
- runtimepy/net/{server/app → html}/bootstrap/tabs.py +3 -24
- runtimepy/net/server/__init__.py +37 -7
- runtimepy/net/server/app/base.py +4 -11
- runtimepy/net/server/app/create.py +1 -1
- runtimepy/net/server/app/env/__init__.py +2 -5
- runtimepy/net/server/app/env/modal.py +2 -2
- runtimepy/net/server/app/env/settings.py +2 -2
- runtimepy/net/server/app/env/tab/base.py +1 -1
- runtimepy/net/server/app/env/tab/controls.py +1 -1
- runtimepy/net/server/app/env/tab/html.py +4 -2
- runtimepy/net/server/app/env/widgets.py +1 -1
- runtimepy/net/server/app/files.py +1 -86
- runtimepy/net/server/app/landing_page.py +7 -1
- runtimepy/net/server/app/placeholder.py +2 -2
- runtimepy/net/server/app/sound.py +1 -1
- runtimepy/net/server/app/tab.py +3 -3
- runtimepy/net/server/html.py +7 -5
- {runtimepy-5.7.2.dist-info → runtimepy-5.7.4.dist-info}/METADATA +5 -5
- {runtimepy-5.7.2.dist-info → runtimepy-5.7.4.dist-info}/RECORD +29 -27
- /runtimepy/net/{server/app → html}/bootstrap/__init__.py +0 -0
- {runtimepy-5.7.2.dist-info → runtimepy-5.7.4.dist-info}/LICENSE +0 -0
- {runtimepy-5.7.2.dist-info → runtimepy-5.7.4.dist-info}/WHEEL +0 -0
- {runtimepy-5.7.2.dist-info → runtimepy-5.7.4.dist-info}/entry_points.txt +0 -0
- {runtimepy-5.7.2.dist-info → runtimepy-5.7.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=cb3ed2d01203d78ad794d39500d706f9
|
|
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.
|
|
13
|
+
VERSION = "5.7.4"
|
|
14
14
|
|
|
15
15
|
# runtimepy-specific content.
|
|
16
16
|
METRICS_NAME = "metrics"
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/* Dark is hard-coded initial state (in HTML). */
|
|
2
|
+
let lightMode = false;
|
|
3
|
+
|
|
4
|
+
function lightDarkClick(event) {
|
|
5
|
+
lightMode = !lightMode;
|
|
6
|
+
|
|
7
|
+
document.getElementById("runtimepy")
|
|
8
|
+
.setAttribute("data-bs-theme", lightMode ? "light" : "dark");
|
|
9
|
+
|
|
10
|
+
window.location.hash = lightMode ? "#light-mode" : "";
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
let lightDarkButton = document.getElementById("theme-button");
|
|
14
|
+
if (lightDarkButton) {
|
|
15
|
+
lightDarkButton.addEventListener("click", lightDarkClick);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
if (window.location.hash) {
|
|
19
|
+
let parts = window.location.hash.slice(1).split(",");
|
|
20
|
+
|
|
21
|
+
if (parts.includes("light-mode")) {
|
|
22
|
+
lightDarkButton.click();
|
|
23
|
+
}
|
|
24
|
+
}
|
runtimepy/mixins/logging.py
CHANGED
|
@@ -10,7 +10,7 @@ from typing import Any, Iterable
|
|
|
10
10
|
|
|
11
11
|
# third-party
|
|
12
12
|
import aiofiles
|
|
13
|
-
from vcorelib.logging import LoggerMixin, LoggerType
|
|
13
|
+
from vcorelib.logging import ListLogger, LoggerMixin, LoggerType
|
|
14
14
|
from vcorelib.paths import Pathlike, normalize
|
|
15
15
|
|
|
16
16
|
# internal
|
|
@@ -66,6 +66,25 @@ class LoggerMixinLevelControl(LoggerMixin):
|
|
|
66
66
|
|
|
67
67
|
|
|
68
68
|
LogPaths = Iterable[tuple[LogLevellike, Pathlike]]
|
|
69
|
+
EXT_LOG_EXTRA = {"external": True}
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def handle_safe_log(
|
|
73
|
+
logger: LoggerType, level: int, data: str, safe_to_log: bool
|
|
74
|
+
) -> None:
|
|
75
|
+
"""handle a log filtering scenario."""
|
|
76
|
+
|
|
77
|
+
if safe_to_log:
|
|
78
|
+
logger.log(level, data, extra=EXT_LOG_EXTRA)
|
|
79
|
+
else:
|
|
80
|
+
record = logging.LogRecord(
|
|
81
|
+
logger.name, level, __file__, -1, data, (), None
|
|
82
|
+
)
|
|
83
|
+
record.external = True
|
|
84
|
+
|
|
85
|
+
for handler in logger.handlers: # type: ignore
|
|
86
|
+
if isinstance(handler, ListLogger):
|
|
87
|
+
handler.emit(record)
|
|
69
88
|
|
|
70
89
|
|
|
71
90
|
class LogCaptureMixin:
|
|
@@ -76,7 +95,10 @@ class LogCaptureMixin:
|
|
|
76
95
|
# Open aiofiles handles.
|
|
77
96
|
streams: list[tuple[int, Any]]
|
|
78
97
|
|
|
79
|
-
|
|
98
|
+
# Set false to only forward to ListLogger handlers. Required for when the
|
|
99
|
+
# system log / process-management logs are being forwarded (otherwise also
|
|
100
|
+
# logging would lead to infinite spam).
|
|
101
|
+
safe_to_log = True
|
|
80
102
|
|
|
81
103
|
async def init_log_capture(
|
|
82
104
|
self, stack: AsyncExitStack, log_paths: LogPaths
|
|
@@ -98,7 +120,8 @@ class LogCaptureMixin:
|
|
|
98
120
|
|
|
99
121
|
def log_line(self, level: int, data: str) -> None:
|
|
100
122
|
"""Log a line for output."""
|
|
101
|
-
|
|
123
|
+
|
|
124
|
+
handle_safe_log(self.logger, level, data, self.safe_to_log)
|
|
102
125
|
|
|
103
126
|
async def dispatch_log_capture(self) -> None:
|
|
104
127
|
"""Get the next line from this log stream."""
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
"""
|
|
2
|
+
A module implementing HTML-related interfaces.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
# built-in
|
|
6
|
+
from io import StringIO
|
|
7
|
+
from typing import Optional
|
|
8
|
+
|
|
9
|
+
# third-party
|
|
10
|
+
from svgen.element import Element
|
|
11
|
+
from svgen.element.html import Html, div
|
|
12
|
+
from vcorelib import DEFAULT_ENCODING
|
|
13
|
+
from vcorelib.io import IndentedFileWriter
|
|
14
|
+
from vcorelib.paths import find_file
|
|
15
|
+
|
|
16
|
+
# internal
|
|
17
|
+
from runtimepy import PKG_NAME
|
|
18
|
+
from runtimepy.net.html.bootstrap import (
|
|
19
|
+
add_bootstrap_css,
|
|
20
|
+
add_bootstrap_js,
|
|
21
|
+
icon_str,
|
|
22
|
+
)
|
|
23
|
+
from runtimepy.net.html.bootstrap.elements import (
|
|
24
|
+
bootstrap_button,
|
|
25
|
+
centered_markdown,
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def create_app_shell(parent: Element, **kwargs) -> tuple[Element, Element]:
|
|
30
|
+
"""Create a bootstrap-based application shell."""
|
|
31
|
+
|
|
32
|
+
container = div(parent=parent, **kwargs)
|
|
33
|
+
container.add_class("d-flex", "align-items-start", "bg-body")
|
|
34
|
+
|
|
35
|
+
# Dark theme.
|
|
36
|
+
container["data-bs-theme"] = "dark"
|
|
37
|
+
|
|
38
|
+
# Buttons.
|
|
39
|
+
button_column = div(parent=container)
|
|
40
|
+
button_column.add_class("d-flex", "flex-column", "h-100", "bg-dark-subtle")
|
|
41
|
+
|
|
42
|
+
# Dark/light theme switch button.
|
|
43
|
+
bootstrap_button(
|
|
44
|
+
icon_str("lightbulb"),
|
|
45
|
+
tooltip=" Toggle light/dark.",
|
|
46
|
+
id="theme-button",
|
|
47
|
+
parent=button_column,
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
return container, button_column
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def markdown_page(parent: Element, markdown: str, **kwargs) -> None:
|
|
54
|
+
"""Compose a landing page."""
|
|
55
|
+
|
|
56
|
+
container = centered_markdown(
|
|
57
|
+
create_app_shell(parent, **kwargs)[0], markdown, "h-100", "text-body"
|
|
58
|
+
)
|
|
59
|
+
container.add_class("overflow-y-auto")
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def common_css(document: Html) -> None:
|
|
63
|
+
"""Add common CSS to an HTML document."""
|
|
64
|
+
|
|
65
|
+
append_kind(document.head, "font", kind="css", tag="style")
|
|
66
|
+
add_bootstrap_css(document.head)
|
|
67
|
+
append_kind(
|
|
68
|
+
document.head, "main", "bootstrap_extra", kind="css", tag="style"
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def full_markdown_page(document: Html, markdown: str) -> None:
|
|
73
|
+
"""Render a full markdown HTML app."""
|
|
74
|
+
|
|
75
|
+
common_css(document)
|
|
76
|
+
markdown_page(document.body, markdown, id=PKG_NAME)
|
|
77
|
+
|
|
78
|
+
# JavaScript.
|
|
79
|
+
append_kind(document.body, "markdown_page")
|
|
80
|
+
add_bootstrap_js(document.body)
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def handle_worker(writer: IndentedFileWriter) -> int:
|
|
84
|
+
"""Boilerplate contents for worker thread block."""
|
|
85
|
+
|
|
86
|
+
# Not currently used.
|
|
87
|
+
# return write_found_file(
|
|
88
|
+
# writer, kind_url("js", "webgl-debug", subdir="third-party")
|
|
89
|
+
# )
|
|
90
|
+
del writer
|
|
91
|
+
|
|
92
|
+
return 0
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def write_found_file(writer: IndentedFileWriter, *args, **kwargs) -> bool:
|
|
96
|
+
"""Write a file's contents to the file-writer's stream."""
|
|
97
|
+
|
|
98
|
+
result = False
|
|
99
|
+
|
|
100
|
+
entry = find_file(*args, **kwargs)
|
|
101
|
+
if entry is not None:
|
|
102
|
+
with entry.open(encoding=DEFAULT_ENCODING) as path_fd:
|
|
103
|
+
for line in path_fd:
|
|
104
|
+
writer.write(line)
|
|
105
|
+
|
|
106
|
+
result = True
|
|
107
|
+
|
|
108
|
+
return result
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def kind_url(
|
|
112
|
+
kind: str, name: str, subdir: str = None, package: str = PKG_NAME
|
|
113
|
+
) -> str:
|
|
114
|
+
"""Return a URL to find a package resource."""
|
|
115
|
+
|
|
116
|
+
path = kind
|
|
117
|
+
|
|
118
|
+
if subdir is not None:
|
|
119
|
+
path += "/" + subdir
|
|
120
|
+
|
|
121
|
+
path += f"/{name}"
|
|
122
|
+
|
|
123
|
+
return f"package://{package}/{path}.{kind}"
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
WORKER_TYPE = "text/js-worker"
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
def append_kind(
|
|
130
|
+
element: Element,
|
|
131
|
+
*names: str,
|
|
132
|
+
package: str = PKG_NAME,
|
|
133
|
+
kind: str = "js",
|
|
134
|
+
tag: str = "script",
|
|
135
|
+
subdir: str = None,
|
|
136
|
+
worker: bool = False,
|
|
137
|
+
) -> Optional[Element]:
|
|
138
|
+
"""Append a new script element."""
|
|
139
|
+
|
|
140
|
+
elem = Element(tag=tag, allow_no_end_tag=False)
|
|
141
|
+
|
|
142
|
+
with StringIO() as stream:
|
|
143
|
+
writer = IndentedFileWriter(stream, per_indent=2)
|
|
144
|
+
found_count = 0
|
|
145
|
+
for name in names:
|
|
146
|
+
if write_found_file(
|
|
147
|
+
writer, kind_url(kind, name, subdir=subdir, package=package)
|
|
148
|
+
):
|
|
149
|
+
found_count += 1
|
|
150
|
+
|
|
151
|
+
if worker:
|
|
152
|
+
found_count += handle_worker(writer)
|
|
153
|
+
|
|
154
|
+
if found_count:
|
|
155
|
+
elem.text = stream.getvalue()
|
|
156
|
+
|
|
157
|
+
if found_count:
|
|
158
|
+
element.children.append(elem)
|
|
159
|
+
|
|
160
|
+
if worker:
|
|
161
|
+
elem["type"] = WORKER_TYPE
|
|
162
|
+
|
|
163
|
+
return elem if found_count else None
|
|
@@ -12,7 +12,7 @@ from svgen.element.html import div
|
|
|
12
12
|
from vcorelib.io.file_writer import IndentedFileWriter
|
|
13
13
|
|
|
14
14
|
# internal
|
|
15
|
-
from runtimepy.net.
|
|
15
|
+
from runtimepy.net.html.bootstrap import icon_str
|
|
16
16
|
|
|
17
17
|
TEXT = "font-monospace"
|
|
18
18
|
BOOTSTRAP_BUTTON = f"rounded-0 {TEXT} button-bodge text-nowrap"
|
|
@@ -167,7 +167,7 @@ def slider(
|
|
|
167
167
|
|
|
168
168
|
def centered_markdown(
|
|
169
169
|
parent: Element, markdown: str, *container_classes: str
|
|
170
|
-
) ->
|
|
170
|
+
) -> Element:
|
|
171
171
|
"""Add centered markdown."""
|
|
172
172
|
|
|
173
173
|
container = div(parent=parent)
|
|
@@ -198,3 +198,5 @@ def centered_markdown(
|
|
|
198
198
|
div(parent=horiz_container)
|
|
199
199
|
|
|
200
200
|
div(parent=container)
|
|
201
|
+
|
|
202
|
+
return container
|
|
@@ -8,10 +8,9 @@ from svgen.element.html import div
|
|
|
8
8
|
|
|
9
9
|
# internal
|
|
10
10
|
from runtimepy import PKG_NAME
|
|
11
|
-
from runtimepy.net.
|
|
12
|
-
from runtimepy.net.
|
|
11
|
+
from runtimepy.net.html import create_app_shell
|
|
12
|
+
from runtimepy.net.html.bootstrap.elements import (
|
|
13
13
|
BOOTSTRAP_BUTTON,
|
|
14
|
-
bootstrap_button,
|
|
15
14
|
collapse_button,
|
|
16
15
|
flex,
|
|
17
16
|
toggle_button,
|
|
@@ -84,27 +83,7 @@ class TabbedContent:
|
|
|
84
83
|
"""Initialize this instance."""
|
|
85
84
|
|
|
86
85
|
self.name = name
|
|
87
|
-
|
|
88
|
-
# Create application container.
|
|
89
|
-
self.container = div(parent=parent, id=name)
|
|
90
|
-
self.container.add_class("d-flex", "align-items-start", "bg-body")
|
|
91
|
-
|
|
92
|
-
# Dark theme.
|
|
93
|
-
self.container["data-bs-theme"] = "dark"
|
|
94
|
-
|
|
95
|
-
# Buttons.
|
|
96
|
-
self.button_column = div(parent=self.container)
|
|
97
|
-
self.button_column.add_class(
|
|
98
|
-
"d-flex", "flex-column", "h-100", "bg-dark-subtle"
|
|
99
|
-
)
|
|
100
|
-
|
|
101
|
-
# Dark/light theme switch button.
|
|
102
|
-
bootstrap_button(
|
|
103
|
-
icon_str("lightbulb"),
|
|
104
|
-
tooltip=" Toggle light/dark.",
|
|
105
|
-
id="theme-button",
|
|
106
|
-
parent=self.button_column,
|
|
107
|
-
)
|
|
86
|
+
self.container, self.button_column = create_app_shell(parent, id=name)
|
|
108
87
|
|
|
109
88
|
# Toggle tabs button.
|
|
110
89
|
self.add_button("Toggle tabs", f"#{PKG_NAME}-tabs", id="tabs-button")
|
runtimepy/net/server/__init__.py
CHANGED
|
@@ -11,16 +11,19 @@ from pathlib import Path
|
|
|
11
11
|
from typing import Any, Optional, TextIO, Union
|
|
12
12
|
|
|
13
13
|
# third-party
|
|
14
|
-
|
|
14
|
+
import aiofiles
|
|
15
|
+
from vcorelib import DEFAULT_ENCODING
|
|
16
|
+
from vcorelib.io import IndentedFileWriter, JsonObject
|
|
15
17
|
from vcorelib.paths import Pathlike, find_file, normalize
|
|
16
18
|
|
|
17
19
|
# internal
|
|
18
20
|
from runtimepy import DEFAULT_EXT, PKG_NAME
|
|
19
21
|
from runtimepy.channel.environment.command import GLOBAL
|
|
22
|
+
from runtimepy.net.html import full_markdown_page
|
|
20
23
|
from runtimepy.net.http.header import RequestHeader
|
|
21
24
|
from runtimepy.net.http.request_target import PathMaybeQuery
|
|
22
25
|
from runtimepy.net.http.response import ResponseHeader
|
|
23
|
-
from runtimepy.net.server.html import HtmlApp, HtmlApps, html_handler
|
|
26
|
+
from runtimepy.net.server.html import HtmlApp, HtmlApps, get_html, html_handler
|
|
24
27
|
from runtimepy.net.server.json import encode_json, json_handler
|
|
25
28
|
from runtimepy.net.tcp.http import HttpConnection
|
|
26
29
|
from runtimepy.util import normalize_root, path_has_part
|
|
@@ -106,7 +109,7 @@ class RuntimepyServerConnection(HttpConnection):
|
|
|
106
109
|
with favicon.open("rb") as favicon_fd:
|
|
107
110
|
type(self).favicon_data = favicon_fd.read()
|
|
108
111
|
|
|
109
|
-
def try_redirect(
|
|
112
|
+
async def try_redirect(
|
|
110
113
|
self, path: PathMaybeQuery, response: ResponseHeader
|
|
111
114
|
) -> Optional[bytes]:
|
|
112
115
|
"""Try handling any HTTP redirect rules."""
|
|
@@ -123,7 +126,26 @@ class RuntimepyServerConnection(HttpConnection):
|
|
|
123
126
|
|
|
124
127
|
return result
|
|
125
128
|
|
|
126
|
-
def
|
|
129
|
+
async def render_markdown(
|
|
130
|
+
self, path: Path, response: ResponseHeader, **kwargs
|
|
131
|
+
) -> bytes:
|
|
132
|
+
"""Render a markdown file as HTML and return the result."""
|
|
133
|
+
|
|
134
|
+
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
|
+
)
|
|
143
|
+
|
|
144
|
+
response["Content-Type"] = f"text/html; charset={DEFAULT_ENCODING}"
|
|
145
|
+
|
|
146
|
+
return document.encode_str().encode()
|
|
147
|
+
|
|
148
|
+
async def try_file(
|
|
127
149
|
self, path: PathMaybeQuery, response: ResponseHeader
|
|
128
150
|
) -> Optional[bytes]:
|
|
129
151
|
"""Try serving this path as a file directly from the file-system."""
|
|
@@ -133,6 +155,12 @@ class RuntimepyServerConnection(HttpConnection):
|
|
|
133
155
|
# Try serving the path as a file.
|
|
134
156
|
for search in self.paths:
|
|
135
157
|
candidate = search.joinpath(path[0][1:])
|
|
158
|
+
|
|
159
|
+
# 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)
|
|
163
|
+
|
|
136
164
|
if candidate.is_file():
|
|
137
165
|
mime, encoding = mimetypes.guess_type(candidate, strict=False)
|
|
138
166
|
|
|
@@ -146,8 +174,8 @@ class RuntimepyServerConnection(HttpConnection):
|
|
|
146
174
|
self.logger.info("Serving '%s' (MIME: %s)", candidate, mime)
|
|
147
175
|
|
|
148
176
|
# Return the file data.
|
|
149
|
-
with
|
|
150
|
-
result = path_fd.read()
|
|
177
|
+
async with aiofiles.open(candidate, mode="rb") as path_fd:
|
|
178
|
+
result = await path_fd.read()
|
|
151
179
|
|
|
152
180
|
break
|
|
153
181
|
|
|
@@ -223,7 +251,9 @@ class RuntimepyServerConnection(HttpConnection):
|
|
|
223
251
|
|
|
224
252
|
# Try serving a file and handling redirects.
|
|
225
253
|
for handler in [self.try_redirect, self.try_file]:
|
|
226
|
-
result = handler(
|
|
254
|
+
result = await handler(
|
|
255
|
+
request.target.origin_form, response
|
|
256
|
+
)
|
|
227
257
|
if result is not None:
|
|
228
258
|
return result
|
|
229
259
|
|
runtimepy/net/server/app/base.py
CHANGED
|
@@ -11,12 +11,9 @@ from svgen.element.html import Html
|
|
|
11
11
|
# internal
|
|
12
12
|
from runtimepy import PKG_NAME
|
|
13
13
|
from runtimepy.net.arbiter.info import AppInfo
|
|
14
|
-
from runtimepy.net.
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
)
|
|
18
|
-
from runtimepy.net.server.app.bootstrap.tabs import TabbedContent
|
|
19
|
-
from runtimepy.net.server.app.files import append_kind
|
|
14
|
+
from runtimepy.net.html import append_kind, common_css
|
|
15
|
+
from runtimepy.net.html.bootstrap import add_bootstrap_js
|
|
16
|
+
from runtimepy.net.html.bootstrap.tabs import TabbedContent
|
|
20
17
|
|
|
21
18
|
TabPopulater = Callable[[TabbedContent], None]
|
|
22
19
|
|
|
@@ -53,11 +50,7 @@ class WebApplication:
|
|
|
53
50
|
"""Populate the body element with the application."""
|
|
54
51
|
|
|
55
52
|
# CSS.
|
|
56
|
-
|
|
57
|
-
add_bootstrap_css(document.head)
|
|
58
|
-
append_kind(
|
|
59
|
-
document.head, "main", "bootstrap_extra", kind="css", tag="style"
|
|
60
|
-
)
|
|
53
|
+
common_css(document)
|
|
61
54
|
|
|
62
55
|
# Worker code.
|
|
63
56
|
append_kind(
|
|
@@ -11,10 +11,10 @@ from vcorelib.logging import LoggerMixin
|
|
|
11
11
|
|
|
12
12
|
# internal
|
|
13
13
|
from runtimepy.net.arbiter.info import AppInfo
|
|
14
|
+
from runtimepy.net.html.bootstrap.tabs import TabbedContent
|
|
14
15
|
from runtimepy.net.http.header import RequestHeader
|
|
15
16
|
from runtimepy.net.http.response import ResponseHeader
|
|
16
17
|
from runtimepy.net.server.app.base import WebApplication
|
|
17
|
-
from runtimepy.net.server.app.bootstrap.tabs import TabbedContent
|
|
18
18
|
from runtimepy.net.server.html import HtmlApp
|
|
19
19
|
|
|
20
20
|
DOCUMENTS: dict[str, Html] = {}
|
|
@@ -8,11 +8,8 @@ from svgen.element.html import div
|
|
|
8
8
|
# internal
|
|
9
9
|
from runtimepy import PKG_NAME
|
|
10
10
|
from runtimepy.net.arbiter.info import AppInfo
|
|
11
|
-
from runtimepy.net.
|
|
12
|
-
|
|
13
|
-
input_box,
|
|
14
|
-
)
|
|
15
|
-
from runtimepy.net.server.app.bootstrap.tabs import TabbedContent
|
|
11
|
+
from runtimepy.net.html.bootstrap.elements import centered_markdown, input_box
|
|
12
|
+
from runtimepy.net.html.bootstrap.tabs import TabbedContent
|
|
16
13
|
from runtimepy.net.server.app.env.modal import Modal
|
|
17
14
|
from runtimepy.net.server.app.env.settings import plot_settings
|
|
18
15
|
from runtimepy.net.server.app.env.tab import ChannelEnvironmentTab
|
|
@@ -7,8 +7,8 @@ from svgen.element.html import div
|
|
|
7
7
|
|
|
8
8
|
# internal
|
|
9
9
|
from runtimepy import PKG_NAME
|
|
10
|
-
from runtimepy.net.
|
|
11
|
-
from runtimepy.net.
|
|
10
|
+
from runtimepy.net.html.bootstrap.elements import TEXT
|
|
11
|
+
from runtimepy.net.html.bootstrap.tabs import TabbedContent
|
|
12
12
|
|
|
13
13
|
|
|
14
14
|
class Modal:
|
|
@@ -6,8 +6,8 @@ A module implementing an application-settings modal.
|
|
|
6
6
|
from svgen.element.html import div
|
|
7
7
|
|
|
8
8
|
# internal
|
|
9
|
-
from runtimepy.net.
|
|
10
|
-
from runtimepy.net.
|
|
9
|
+
from runtimepy.net.html.bootstrap.elements import flex, slider
|
|
10
|
+
from runtimepy.net.html.bootstrap.tabs import TabbedContent
|
|
11
11
|
from runtimepy.net.server.app.env.modal import Modal
|
|
12
12
|
from runtimepy.net.server.app.placeholder import under_construction
|
|
13
13
|
|
|
@@ -13,7 +13,7 @@ from runtimepy.channel.environment.command.processor import (
|
|
|
13
13
|
ChannelCommandProcessor,
|
|
14
14
|
)
|
|
15
15
|
from runtimepy.net.arbiter.info import AppInfo
|
|
16
|
-
from runtimepy.net.
|
|
16
|
+
from runtimepy.net.html.bootstrap.tabs import TabbedContent
|
|
17
17
|
from runtimepy.net.server.app.tab import Tab
|
|
18
18
|
|
|
19
19
|
|
|
@@ -13,7 +13,7 @@ from svgen.element.html import div
|
|
|
13
13
|
from runtimepy.channel import AnyChannel
|
|
14
14
|
from runtimepy.channel.environment import ChannelEnvironment
|
|
15
15
|
from runtimepy.enum import RuntimeEnum
|
|
16
|
-
from runtimepy.net.
|
|
16
|
+
from runtimepy.net.html.bootstrap.elements import slider, toggle_button
|
|
17
17
|
from runtimepy.net.server.app.env.tab.base import ChannelEnvironmentTabBase
|
|
18
18
|
from runtimepy.net.server.app.env.widgets import (
|
|
19
19
|
TABLE_BUTTON_CLASSES,
|
|
@@ -12,7 +12,7 @@ from svgen.element.html import div
|
|
|
12
12
|
# internal
|
|
13
13
|
from runtimepy.channel import AnyChannel
|
|
14
14
|
from runtimepy.enum import RuntimeEnum
|
|
15
|
-
from runtimepy.net.
|
|
15
|
+
from runtimepy.net.html.bootstrap.elements import (
|
|
16
16
|
TEXT,
|
|
17
17
|
centered_markdown,
|
|
18
18
|
flex,
|
|
@@ -241,7 +241,9 @@ class ChannelEnvironmentTabHtml(ChannelEnvironmentTabControls):
|
|
|
241
241
|
logs = div(
|
|
242
242
|
tag="textarea",
|
|
243
243
|
parent=div(parent=vert_container, class_str="form-floating"),
|
|
244
|
-
class_str=(
|
|
244
|
+
class_str=(
|
|
245
|
+
f"form-control rounded-0 {TEXT} text-body-emphasis text-logs"
|
|
246
|
+
),
|
|
245
247
|
id=self.get_id("logs"),
|
|
246
248
|
title=f"Text logs for {self.name}.",
|
|
247
249
|
)
|
|
@@ -14,7 +14,7 @@ from runtimepy.channel.environment.command.processor import (
|
|
|
14
14
|
ChannelCommandProcessor,
|
|
15
15
|
)
|
|
16
16
|
from runtimepy.enum import RuntimeEnum
|
|
17
|
-
from runtimepy.net.
|
|
17
|
+
from runtimepy.net.html.bootstrap.elements import (
|
|
18
18
|
flex,
|
|
19
19
|
input_box,
|
|
20
20
|
set_tooltip,
|
|
@@ -4,32 +4,14 @@ A module implementing interfaces for working with file contents.
|
|
|
4
4
|
|
|
5
5
|
# built-in
|
|
6
6
|
from io import StringIO
|
|
7
|
-
from typing import Optional
|
|
8
7
|
|
|
9
8
|
# third-party
|
|
10
9
|
from svgen.element import Element
|
|
11
|
-
from vcorelib import DEFAULT_ENCODING
|
|
12
10
|
from vcorelib.io import IndentedFileWriter
|
|
13
|
-
from vcorelib.paths import find_file
|
|
14
11
|
|
|
15
12
|
# internal
|
|
16
13
|
from runtimepy import PKG_NAME
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
def write_found_file(writer: IndentedFileWriter, *args, **kwargs) -> bool:
|
|
20
|
-
"""Write a file's contents to the file-writer's stream."""
|
|
21
|
-
|
|
22
|
-
result = False
|
|
23
|
-
|
|
24
|
-
entry = find_file(*args, **kwargs)
|
|
25
|
-
if entry is not None:
|
|
26
|
-
with entry.open(encoding=DEFAULT_ENCODING) as path_fd:
|
|
27
|
-
for line in path_fd:
|
|
28
|
-
writer.write(line)
|
|
29
|
-
|
|
30
|
-
result = True
|
|
31
|
-
|
|
32
|
-
return result
|
|
14
|
+
from runtimepy.net.html import kind_url, write_found_file
|
|
33
15
|
|
|
34
16
|
|
|
35
17
|
def set_text_to_file(element: Element, *args, **kwargs) -> bool:
|
|
@@ -45,21 +27,6 @@ def set_text_to_file(element: Element, *args, **kwargs) -> bool:
|
|
|
45
27
|
return result
|
|
46
28
|
|
|
47
29
|
|
|
48
|
-
def kind_url(
|
|
49
|
-
kind: str, name: str, subdir: str = None, package: str = PKG_NAME
|
|
50
|
-
) -> str:
|
|
51
|
-
"""Return a URL to find a package resource."""
|
|
52
|
-
|
|
53
|
-
path = kind
|
|
54
|
-
|
|
55
|
-
if subdir is not None:
|
|
56
|
-
path += "/" + subdir
|
|
57
|
-
|
|
58
|
-
path += f"/{name}"
|
|
59
|
-
|
|
60
|
-
return f"package://{package}/{path}.{kind}"
|
|
61
|
-
|
|
62
|
-
|
|
63
30
|
def set_text_to_kind(
|
|
64
31
|
element: Element,
|
|
65
32
|
kind: str,
|
|
@@ -72,55 +39,3 @@ def set_text_to_kind(
|
|
|
72
39
|
return set_text_to_file(
|
|
73
40
|
element, kind_url(kind, name, subdir=subdir, package=package)
|
|
74
41
|
)
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
WORKER_TYPE = "text/js-worker"
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
def handle_worker(writer: IndentedFileWriter) -> int:
|
|
81
|
-
"""Boilerplate contents for worker thread block."""
|
|
82
|
-
|
|
83
|
-
# Not currently used.
|
|
84
|
-
# return write_found_file(
|
|
85
|
-
# writer, kind_url("js", "webgl-debug", subdir="third-party")
|
|
86
|
-
# )
|
|
87
|
-
del writer
|
|
88
|
-
|
|
89
|
-
return 0
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
def append_kind(
|
|
93
|
-
element: Element,
|
|
94
|
-
*names: str,
|
|
95
|
-
package: str = PKG_NAME,
|
|
96
|
-
kind: str = "js",
|
|
97
|
-
tag: str = "script",
|
|
98
|
-
subdir: str = None,
|
|
99
|
-
worker: bool = False,
|
|
100
|
-
) -> Optional[Element]:
|
|
101
|
-
"""Append a new script element."""
|
|
102
|
-
|
|
103
|
-
elem = Element(tag=tag, allow_no_end_tag=False)
|
|
104
|
-
|
|
105
|
-
with StringIO() as stream:
|
|
106
|
-
writer = IndentedFileWriter(stream, per_indent=2)
|
|
107
|
-
found_count = 0
|
|
108
|
-
for name in names:
|
|
109
|
-
if write_found_file(
|
|
110
|
-
writer, kind_url(kind, name, subdir=subdir, package=package)
|
|
111
|
-
):
|
|
112
|
-
found_count += 1
|
|
113
|
-
|
|
114
|
-
if worker:
|
|
115
|
-
found_count += handle_worker(writer)
|
|
116
|
-
|
|
117
|
-
if found_count:
|
|
118
|
-
elem.text = stream.getvalue()
|
|
119
|
-
|
|
120
|
-
if found_count:
|
|
121
|
-
element.children.append(elem)
|
|
122
|
-
|
|
123
|
-
if worker:
|
|
124
|
-
elem["type"] = WORKER_TYPE
|
|
125
|
-
|
|
126
|
-
return elem if found_count else None
|
|
@@ -10,6 +10,7 @@ from svgen.element.html import Html
|
|
|
10
10
|
|
|
11
11
|
# internal
|
|
12
12
|
from runtimepy.net.arbiter.info import AppInfo
|
|
13
|
+
from runtimepy.net.html import full_markdown_page
|
|
13
14
|
from runtimepy.net.http.header import RequestHeader
|
|
14
15
|
from runtimepy.net.http.response import ResponseHeader
|
|
15
16
|
|
|
@@ -28,6 +29,11 @@ def landing_page(
|
|
|
28
29
|
del response
|
|
29
30
|
del request_data
|
|
30
31
|
|
|
31
|
-
|
|
32
|
+
full_markdown_page(
|
|
33
|
+
document,
|
|
34
|
+
app.config_param("landing_page", {}, strict=True).get( # type: ignore
|
|
35
|
+
"markdown", "no data"
|
|
36
|
+
),
|
|
37
|
+
)
|
|
32
38
|
|
|
33
39
|
return document
|
|
@@ -8,8 +8,8 @@ from svgen.element.html import div
|
|
|
8
8
|
|
|
9
9
|
# internal
|
|
10
10
|
from runtimepy.net.arbiter.info import AppInfo
|
|
11
|
-
from runtimepy.net.
|
|
12
|
-
from runtimepy.net.
|
|
11
|
+
from runtimepy.net.html.bootstrap import icon_str
|
|
12
|
+
from runtimepy.net.html.bootstrap.tabs import TabbedContent
|
|
13
13
|
from runtimepy.net.server.app.tab import Tab
|
|
14
14
|
|
|
15
15
|
|
|
@@ -7,7 +7,7 @@ from svgen.element import Element
|
|
|
7
7
|
from svgen.element.html import div
|
|
8
8
|
|
|
9
9
|
# built-in
|
|
10
|
-
from runtimepy.net.
|
|
10
|
+
from runtimepy.net.html.bootstrap.elements import bootstrap_button
|
|
11
11
|
from runtimepy.net.server.app.tab import Tab
|
|
12
12
|
|
|
13
13
|
|
runtimepy/net/server/app/tab.py
CHANGED
|
@@ -13,9 +13,9 @@ from vcorelib.io.file_writer import IndentedFileWriter
|
|
|
13
13
|
|
|
14
14
|
# internal
|
|
15
15
|
from runtimepy.net.arbiter.info import AppInfo
|
|
16
|
-
from runtimepy.net.
|
|
17
|
-
from runtimepy.net.
|
|
18
|
-
from runtimepy.net.
|
|
16
|
+
from runtimepy.net.html import kind_url, write_found_file
|
|
17
|
+
from runtimepy.net.html.bootstrap import icon_str
|
|
18
|
+
from runtimepy.net.html.bootstrap.tabs import TabbedContent
|
|
19
19
|
|
|
20
20
|
|
|
21
21
|
class Tab:
|
runtimepy/net/server/html.py
CHANGED
|
@@ -20,6 +20,12 @@ HtmlApp = Callable[
|
|
|
20
20
|
HtmlApps = dict[str, HtmlApp]
|
|
21
21
|
|
|
22
22
|
|
|
23
|
+
def get_html() -> Html:
|
|
24
|
+
"""Get a default HTML document."""
|
|
25
|
+
|
|
26
|
+
return Html(HttpConnection.identity)
|
|
27
|
+
|
|
28
|
+
|
|
23
29
|
async def html_handler(
|
|
24
30
|
apps: HtmlApps,
|
|
25
31
|
stream: TextIO,
|
|
@@ -36,8 +42,4 @@ async def html_handler(
|
|
|
36
42
|
# Create the application.
|
|
37
43
|
app = apps.get(request.target.path, default_app)
|
|
38
44
|
if app is not None:
|
|
39
|
-
(
|
|
40
|
-
await app(
|
|
41
|
-
Html(HttpConnection.identity), request, response, request_data
|
|
42
|
-
)
|
|
43
|
-
).render(stream)
|
|
45
|
+
(await app(get_html(), request, response, request_data)).render(stream)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: runtimepy
|
|
3
|
-
Version: 5.7.
|
|
3
|
+
Version: 5.7.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,10 +17,10 @@ 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: vcorelib >=3.4.2
|
|
21
|
-
Requires-Dist: websockets
|
|
22
20
|
Requires-Dist: aiofiles
|
|
23
21
|
Requires-Dist: psutil
|
|
22
|
+
Requires-Dist: websockets
|
|
23
|
+
Requires-Dist: vcorelib >=3.4.2
|
|
24
24
|
Requires-Dist: svgen >=0.6.8
|
|
25
25
|
Provides-Extra: test
|
|
26
26
|
Requires-Dist: pylint ; 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=
|
|
48
|
+
hash=fbb71900eae64b008d2a2df1b7dde92b
|
|
49
49
|
=====================================
|
|
50
50
|
-->
|
|
51
51
|
|
|
52
|
-
# runtimepy ([5.7.
|
|
52
|
+
# runtimepy ([5.7.4](https://pypi.org/project/runtimepy/))
|
|
53
53
|
|
|
54
54
|
[](https://pypi.org/project/runtimepy/)
|
|
55
55
|

|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
runtimepy/__init__.py,sha256=
|
|
1
|
+
runtimepy/__init__.py,sha256=PWwxhEEdCroFpm1bLs0ARQ08yoplDS1rmSMU3uDL-P4,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
|
|
@@ -59,6 +59,7 @@ runtimepy/data/js/audio.js,sha256=bLkBqbeHMiGGidfL3iXjmVoF9seK-ZeZ3kwgOrcpgk4,10
|
|
|
59
59
|
runtimepy/data/js/events.js,sha256=rgz3Q_8J6sfU_7Sa7fG1mZD0pQ4S3vwN2mqcvQfePkM,554
|
|
60
60
|
runtimepy/data/js/init.js,sha256=IeFqfab7CM2-Z4fIbyGaUD4M2orUT8uLwcVlleQqXzg,1522
|
|
61
61
|
runtimepy/data/js/main.js,sha256=nYIQ6O76EWqlzwX7oEwPXqC-LCUFCZYDADK9QbYRDKk,404
|
|
62
|
+
runtimepy/data/js/markdown_page.js,sha256=pygLkO6P1AJnOy5PjIUH_px1OEiROrSNLGLUFuERMJc,610
|
|
62
63
|
runtimepy/data/js/util.js,sha256=Xc8pHUiFDBDvIqTamWrCYUOpF7iR9VNvPDCSCQAfLDA,1424
|
|
63
64
|
runtimepy/data/js/worker.js,sha256=V9deGAynjvUr1D-WGi3wUW8rxoaNLvBvayMoLFZk3w0,2444
|
|
64
65
|
runtimepy/data/js/classes/App.js,sha256=nnY42Q3tlNzf8JZtuGKyxJZLLNMfResdww8svOQMC3U,3402
|
|
@@ -131,7 +132,7 @@ runtimepy/mixins/async_command.py,sha256=xZNTiRo_Kd_aJboLuFOkQyMo2Exn8ENyY483zdw
|
|
|
131
132
|
runtimepy/mixins/enum.py,sha256=IRQR7HD8J0uoxahNqb-2LIVokFn1L2-v9I5HNFw9W3s,719
|
|
132
133
|
runtimepy/mixins/environment.py,sha256=9dCy7nL1bwZY1p-ez8zy9Jf_6zhljSESnK9F9wtRdl8,3955
|
|
133
134
|
runtimepy/mixins/finalize.py,sha256=pTziopAWXpyRy0I8UZZv8Q4abXvnH3RrQ_dt3Rh6xlA,1600
|
|
134
|
-
runtimepy/mixins/logging.py,sha256=
|
|
135
|
+
runtimepy/mixins/logging.py,sha256=Z5zTIImkkwK0BVhm-4hEP6dzq_8pRkC9wYBCkRskmlc,3735
|
|
135
136
|
runtimepy/mixins/psutil.py,sha256=RlaEuyQ0-TynQxYW85vFuPiQ-29T2mIrsdaDlpSJq1s,1293
|
|
136
137
|
runtimepy/mixins/regex.py,sha256=kpCj4iL1akzt_KPPiMP-bTbuLBHOpkUrwbCTRe8HSUk,1061
|
|
137
138
|
runtimepy/mixins/trig.py,sha256=vkDd9Rh8080gvH5OHkSYmjImVgM_ZZ7RzMxsczKx5N4,2480
|
|
@@ -164,6 +165,10 @@ runtimepy/net/arbiter/struct/__init__.py,sha256=Vr38dp2X0PZOrAbjKsZ9xZdQ1j3z92s4
|
|
|
164
165
|
runtimepy/net/arbiter/tcp/__init__.py,sha256=djNm8il_9aLNpGsYResJlFmyIqx9XNLqVay-mYnn8vc,1530
|
|
165
166
|
runtimepy/net/arbiter/tcp/json.py,sha256=W9a_OwBPmIoB2XZf4iuAIWQhMg2qA9xejBhGBdNCPnI,742
|
|
166
167
|
runtimepy/net/factories/__init__.py,sha256=rPdBVpgzzQYF61w6efQrEre71yMPHd6kanBpMdOX-3c,4672
|
|
168
|
+
runtimepy/net/html/__init__.py,sha256=BQeGpZWfGSmMg1R0N9GaOZfyFn4UQGHKoFOhd-1G75Q,3983
|
|
169
|
+
runtimepy/net/html/bootstrap/__init__.py,sha256=ONhwx68piWjsrf88FMpda84TWSPqgi-RZCBuWCci_ak,1444
|
|
170
|
+
runtimepy/net/html/bootstrap/elements.py,sha256=8sq79EPR8TF9oYV_4I0Sba_PikHOpEaxUvQ7bqtm0ow,4800
|
|
171
|
+
runtimepy/net/html/bootstrap/tabs.py,sha256=7-0lJOD9SALmsViUYGJAXF0PTSqtffc4mpoFwmYcnXE,3842
|
|
167
172
|
runtimepy/net/http/__init__.py,sha256=4TjFp_ajAVcOEvwtjlF6mG-9EbEePqFZht-QpWIKVBo,1802
|
|
168
173
|
runtimepy/net/http/common.py,sha256=vpoO6XwRmrZmTkCu9bkI0HnyaD8MWTpV7ADesCNrfRE,2237
|
|
169
174
|
runtimepy/net/http/header.py,sha256=AECSdvhBA9_5Pg3UdwMzsmBpcqgsiPj41xnIGPm5g5E,2296
|
|
@@ -171,30 +176,27 @@ runtimepy/net/http/request_target.py,sha256=EE1aI5VSARw1h93jyZvP56ir5O5fjd6orYK-
|
|
|
171
176
|
runtimepy/net/http/response.py,sha256=Sup8W_A0ADNzR5olKrQsVNhsQXUwPOD-eJLlLOgYlAY,2316
|
|
172
177
|
runtimepy/net/http/state.py,sha256=qCMN8aWfCRfU9XP-cIhSOo2RqfljTjbQRCflfcy2bfY,1626
|
|
173
178
|
runtimepy/net/http/version.py,sha256=mp6rgIM7-VUVKLCA0Uw96CmBkL0ET860lDVVEewpZ7w,1098
|
|
174
|
-
runtimepy/net/server/__init__.py,sha256=
|
|
175
|
-
runtimepy/net/server/html.py,sha256=
|
|
179
|
+
runtimepy/net/server/__init__.py,sha256=Yt2ltmiQDkVNjvYCqFh1kHlK0eelWYVHwQNkJxozta0,8946
|
|
180
|
+
runtimepy/net/server/html.py,sha256=dlVqIEDTdAhU7NK84sTqXqGxHpqndsWS36Kgzy9MJdE,1189
|
|
176
181
|
runtimepy/net/server/json.py,sha256=a7vM5yfq2er4DexzFqEMnxoMGDeuywKkVH4-uNJBAik,2522
|
|
177
182
|
runtimepy/net/server/app/__init__.py,sha256=Q5NWlAkIZE2oEHkGdILFyQoX1Fw1lMR1lVQyMVkJ_Hc,2989
|
|
178
|
-
runtimepy/net/server/app/base.py,sha256=
|
|
179
|
-
runtimepy/net/server/app/create.py,sha256=
|
|
183
|
+
runtimepy/net/server/app/base.py,sha256=HF_Qa3ufrZNaYBVnBwGi-Siv3nneqEo01j5h5pK-ZTk,1871
|
|
184
|
+
runtimepy/net/server/app/create.py,sha256=eRT8qxubht5A7149Xol3Z8rkdYd_pjNLqrlyMnXk-Zg,2660
|
|
180
185
|
runtimepy/net/server/app/elements.py,sha256=KJt9vWqkfvniJMiLOJN467JjPPrEqJYZXmDuY1JoY1g,455
|
|
181
|
-
runtimepy/net/server/app/files.py,sha256=
|
|
182
|
-
runtimepy/net/server/app/landing_page.py,sha256=
|
|
183
|
-
runtimepy/net/server/app/placeholder.py,sha256=
|
|
186
|
+
runtimepy/net/server/app/files.py,sha256=9EiGA5aYczJN6BJifAIZ8e3wBbIGCekVLCu0D54ZAFc,968
|
|
187
|
+
runtimepy/net/server/app/landing_page.py,sha256=nO7uIO30Sw3R41qH8I1q9RWk1RFLDy8JhlrkA3avTQQ,870
|
|
188
|
+
runtimepy/net/server/app/placeholder.py,sha256=OuiMNvLEK0pI2N3oIqvPRaperoJkDg-fBds9HHfuosg,1664
|
|
184
189
|
runtimepy/net/server/app/pyodide.py,sha256=dGJ4u78eYQLU9RQbZEWgzv-7jVIwblS6VopibG82tA4,478
|
|
185
|
-
runtimepy/net/server/app/sound.py,sha256=
|
|
186
|
-
runtimepy/net/server/app/tab.py,sha256=
|
|
187
|
-
runtimepy/net/server/app/
|
|
188
|
-
runtimepy/net/server/app/
|
|
189
|
-
runtimepy/net/server/app/
|
|
190
|
-
runtimepy/net/server/app/env/
|
|
191
|
-
runtimepy/net/server/app/env/modal.py,sha256=BDnZvdzwu68ZCKISab39n8_NRWh518IyrtObovhC8SU,1752
|
|
192
|
-
runtimepy/net/server/app/env/settings.py,sha256=2dJydD7_lH8ae43d0D28BNRCbUjmmq4gc-eEAqDOCHs,1732
|
|
193
|
-
runtimepy/net/server/app/env/widgets.py,sha256=_kNvPl7MXnZOiwTjoZiU2hfuSjkLnRUrORTVDi3w7Ls,5312
|
|
190
|
+
runtimepy/net/server/app/sound.py,sha256=qG2k00nWRPAmI5_4L_LMs10nsCTBKaAzIp80embgua8,837
|
|
191
|
+
runtimepy/net/server/app/tab.py,sha256=gRiaUJdB3V9hIKI5MksW7spNChfMtEMDFWCTP1ERrZ4,2272
|
|
192
|
+
runtimepy/net/server/app/env/__init__.py,sha256=_FcgefASOwifwT0m5opg8jQbpZAVoedhNxWw0v1VB1k,4147
|
|
193
|
+
runtimepy/net/server/app/env/modal.py,sha256=HTipCYgQaAUtsmlBjXKfhAM5JyhLqoIIwEwsPnKhrG8,1740
|
|
194
|
+
runtimepy/net/server/app/env/settings.py,sha256=DboR8vXrdGeB_ehP9USvnyUtzgo4JR5CyYV9AGLYHGI,1720
|
|
195
|
+
runtimepy/net/server/app/env/widgets.py,sha256=ccrkJNikL5VEKDaTMd8FSI9VzjYYHcpuIRdDjvpQtug,5306
|
|
194
196
|
runtimepy/net/server/app/env/tab/__init__.py,sha256=stTVKyHljLQWnnhxkWPwa7bLdZtjhiMFbiVFgbiYaFI,647
|
|
195
|
-
runtimepy/net/server/app/env/tab/base.py,sha256=
|
|
196
|
-
runtimepy/net/server/app/env/tab/controls.py,sha256=
|
|
197
|
-
runtimepy/net/server/app/env/tab/html.py,sha256=
|
|
197
|
+
runtimepy/net/server/app/env/tab/base.py,sha256=v5-Zbo_NqRqoLuceYclz348oFHcL68T2mbEh4EDWtTg,1162
|
|
198
|
+
runtimepy/net/server/app/env/tab/controls.py,sha256=bifFMvshDNsar3UiqeXOCYi71JGFRlMnyixKXrdLAEI,4728
|
|
199
|
+
runtimepy/net/server/app/env/tab/html.py,sha256=IfKCQ_2qupIRtWIuodIBM8XAal1esSXovht1SeGyvb4,7173
|
|
198
200
|
runtimepy/net/server/app/env/tab/message.py,sha256=OWqBIPRt6UdBHAXk5qvFMbnWuvIRUyp34lzb3GYdthk,4070
|
|
199
201
|
runtimepy/net/server/struct/__init__.py,sha256=Zy37r6RLFu-XFr9vsanSq80BJdS6Dxr7zmPzQbb7xdw,1799
|
|
200
202
|
runtimepy/net/server/websocket/__init__.py,sha256=KISuFUUQwNn6BXo8BOMuMOXyoVqE7Jw94ZQiSCQuRQE,5279
|
|
@@ -280,9 +282,9 @@ runtimepy/tui/task.py,sha256=nUZo9fuOC-k1Wpqdzkv9v1tQirCI28fZVgcC13Ijvus,1093
|
|
|
280
282
|
runtimepy/tui/channels/__init__.py,sha256=evDaiIn-YS9uGhdo8ZGtP9VK1ek6sr_P1nJ9JuSET0o,4536
|
|
281
283
|
runtimepy/ui/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
282
284
|
runtimepy/ui/controls.py,sha256=yvT7h3thbYaitsakcIAJ90EwKzJ4b-jnc6p3UuVf_XE,1241
|
|
283
|
-
runtimepy-5.7.
|
|
284
|
-
runtimepy-5.7.
|
|
285
|
-
runtimepy-5.7.
|
|
286
|
-
runtimepy-5.7.
|
|
287
|
-
runtimepy-5.7.
|
|
288
|
-
runtimepy-5.7.
|
|
285
|
+
runtimepy-5.7.4.dist-info/LICENSE,sha256=okYCYhGsx_BlzvFdoNVBVpw_Cfb4SOqHA_VAARml4Hc,1071
|
|
286
|
+
runtimepy-5.7.4.dist-info/METADATA,sha256=TN5nOZ_PyKZP_k6k5UW13hOrSEGKpgthVPvjw3h0GRs,9308
|
|
287
|
+
runtimepy-5.7.4.dist-info/WHEEL,sha256=OVMc5UfuAQiSplgO0_WdW7vXVGAt9Hdd6qtN4HotdyA,91
|
|
288
|
+
runtimepy-5.7.4.dist-info/entry_points.txt,sha256=-btVBkYv7ybcopqZ_pRky-bEzu3vhbaG3W3Z7ERBiFE,51
|
|
289
|
+
runtimepy-5.7.4.dist-info/top_level.txt,sha256=0jPmh6yqHyyJJDwEID-LpQly-9kQ3WRMjH7Lix8peLg,10
|
|
290
|
+
runtimepy-5.7.4.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|