instaui 0.1.0__py3-none-any.whl → 0.1.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.
- instaui/components/component.py +1 -1
- instaui/components/element.py +37 -17
- instaui/components/html/checkbox.py +0 -7
- instaui/components/slot.py +2 -3
- instaui/components/vfor.py +1 -1
- instaui/dependencies/component_dependency.py +16 -0
- instaui/dependencies/plugin_dependency.py +28 -0
- instaui/fastapi_server/debug_mode_router.py +0 -1
- instaui/fastapi_server/dependency_router.py +21 -0
- instaui/fastapi_server/resource.py +35 -0
- instaui/fastapi_server/server.py +124 -100
- instaui/html_tools.py +12 -106
- instaui/page_info.py +1 -11
- instaui/runtime/_app.py +9 -20
- instaui/runtime/resource.py +11 -46
- instaui/spa_router/_file_base_utils.py +47 -42
- instaui/spa_router/_route_model.py +3 -25
- instaui/spa_router/templates/page_routes +1 -0
- instaui/static/insta-ui.esm-browser.prod.js +3663 -3663
- instaui/static/insta-ui.iife.js +29 -29
- instaui/static/templates/web.html +32 -76
- instaui/static/templates/zero.html +48 -32
- instaui/systems/file_system.py +0 -9
- instaui/template/web_template.py +40 -46
- instaui/template/zero_template.py +100 -15
- instaui/ui/__init__.py +2 -5
- instaui/ui_functions/ui_page.py +3 -18
- instaui/vars/path_var.py +2 -1
- instaui/zero/func.py +111 -0
- instaui/zero/scope.py +12 -1
- {instaui-0.1.0.dist-info → instaui-0.1.2.dist-info}/METADATA +1 -1
- {instaui-0.1.0.dist-info → instaui-0.1.2.dist-info}/RECORD +34 -33
- instaui/dependencies/__init__.py +0 -15
- instaui/dependencies/component_registrar.py +0 -82
- instaui/dependencies/installer.py +0 -5
- instaui/fastapi_server/config_router.py +0 -60
- {instaui-0.1.0.dist-info → instaui-0.1.2.dist-info}/LICENSE +0 -0
- {instaui-0.1.0.dist-info → instaui-0.1.2.dist-info}/WHEEL +0 -0
instaui/components/component.py
CHANGED
instaui/components/element.py
CHANGED
@@ -13,6 +13,7 @@ from typing import (
|
|
13
13
|
Optional,
|
14
14
|
Tuple,
|
15
15
|
Union,
|
16
|
+
cast,
|
16
17
|
overload,
|
17
18
|
TYPE_CHECKING,
|
18
19
|
)
|
@@ -21,11 +22,11 @@ from collections import defaultdict
|
|
21
22
|
from instaui.runtime._app import get_app_slot
|
22
23
|
from instaui.runtime._app import get_current_scope
|
23
24
|
from instaui.vars.element_ref import ElementRef
|
24
|
-
|
25
|
-
|
26
25
|
from instaui.vars.vfor_item import VForItem
|
27
26
|
from instaui.components.directive import Directive
|
28
|
-
from instaui.dependencies import
|
27
|
+
from instaui.dependencies.component_dependency import (
|
28
|
+
ComponentDependencyInfo,
|
29
|
+
)
|
29
30
|
from .slot import SlotManager, Slot
|
30
31
|
from instaui import consts
|
31
32
|
from instaui.components.component import Component
|
@@ -69,14 +70,14 @@ PROPS_PATTERN = re.compile(
|
|
69
70
|
|
70
71
|
|
71
72
|
class Element(Component):
|
72
|
-
|
73
|
+
dependency: ClassVar[Optional[ComponentDependencyInfo]] = None
|
73
74
|
_default_props: ClassVar[Dict[str, Any]] = {}
|
74
75
|
_default_classes: ClassVar[List[str]] = []
|
75
76
|
_default_style: ClassVar[Dict[str, str]] = {}
|
76
77
|
|
77
78
|
def __init__(self, tag: Optional[Union[str, ElementBindingMixin]] = None):
|
78
|
-
if self.
|
79
|
-
tag = self.
|
79
|
+
if self.dependency:
|
80
|
+
tag = self.dependency.tag_name or ""
|
80
81
|
|
81
82
|
super().__init__(tag)
|
82
83
|
|
@@ -101,19 +102,28 @@ class Element(Component):
|
|
101
102
|
def __init_subclass__(
|
102
103
|
cls,
|
103
104
|
*,
|
104
|
-
|
105
|
+
esm: Union[str, Path, None] = None,
|
106
|
+
externals: Optional[List[Union[str, Path]]] = None,
|
107
|
+
css: Union[List[Union[str, Path]], None] = None,
|
105
108
|
) -> None:
|
106
109
|
super().__init_subclass__()
|
107
110
|
|
108
|
-
if
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
111
|
+
if esm:
|
112
|
+
esm = _make_dependency_path(esm, cls)
|
113
|
+
|
114
|
+
if externals:
|
115
|
+
externals = [_make_dependency_path(e, cls) for e in externals]
|
116
|
+
|
117
|
+
if css:
|
118
|
+
css = [_make_dependency_path(c, cls) for c in css]
|
113
119
|
|
114
|
-
|
115
|
-
|
116
|
-
|
120
|
+
tag_name = f"instaui-{esm.stem}"
|
121
|
+
|
122
|
+
cls.dependency = ComponentDependencyInfo(
|
123
|
+
tag_name=tag_name,
|
124
|
+
esm=esm,
|
125
|
+
externals=cast(List[Path], externals or []),
|
126
|
+
css=cast(List[Path], css or []),
|
117
127
|
)
|
118
128
|
|
119
129
|
cls._default_props = copy(cls._default_props)
|
@@ -365,8 +375,8 @@ class Element(Component):
|
|
365
375
|
if self._directives:
|
366
376
|
data["dir"] = list(self._directives.keys())
|
367
377
|
|
368
|
-
if self.
|
369
|
-
get_app_slot().
|
378
|
+
if self.dependency:
|
379
|
+
get_app_slot().use_component_dependency(self.dependency)
|
370
380
|
|
371
381
|
if self._element_ref:
|
372
382
|
scope = get_current_scope()
|
@@ -460,3 +470,13 @@ def _classifyBindableDict(
|
|
460
470
|
value_data[key] = value
|
461
471
|
|
462
472
|
return value_data, bind_data
|
473
|
+
|
474
|
+
|
475
|
+
def _make_dependency_path(path: Union[str, Path], cls: type):
|
476
|
+
if isinstance(path, str):
|
477
|
+
path = Path(path)
|
478
|
+
|
479
|
+
if not path.is_absolute():
|
480
|
+
path = Path(inspect.getfile(cls)).parent / path
|
481
|
+
|
482
|
+
return path
|
@@ -31,12 +31,5 @@ class Checkbox(InputEventMixin, ValueElement[Union[bool, str]]):
|
|
31
31
|
if model_value is not None:
|
32
32
|
self.props({"value": model_value})
|
33
33
|
|
34
|
-
# def vmodel(
|
35
|
-
# self,
|
36
|
-
# value: Any,
|
37
|
-
# *modifiers: Literal["trim"] | Literal["number"] | Literal["lazy"],
|
38
|
-
# ):
|
39
|
-
# return super().vmodel(value, *modifiers) # type: ignore
|
40
|
-
|
41
34
|
def _input_event_mixin_element(self) -> Element:
|
42
35
|
return self
|
instaui/components/slot.py
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
|
3
|
-
from typing import TYPE_CHECKING, Dict, List, Optional, Set
|
3
|
+
from typing import TYPE_CHECKING, Dict, List, Optional, Set
|
4
4
|
from instaui.common.jsonable import Jsonable
|
5
5
|
from instaui.runtime import get_slot_stacks, pop_slot
|
6
6
|
from instaui.runtime._app import get_app_slot
|
@@ -8,7 +8,6 @@ from instaui.vars.slot_prop import BindingSlotPropItem
|
|
8
8
|
|
9
9
|
if TYPE_CHECKING:
|
10
10
|
from instaui.components.component import Component
|
11
|
-
from instaui.components.vfor import VFor
|
12
11
|
|
13
12
|
_DEFAULT_SLOT_NAME = ":"
|
14
13
|
|
@@ -50,7 +49,7 @@ class Slot(Jsonable):
|
|
50
49
|
|
51
50
|
self._id: Optional[str] = None
|
52
51
|
self._name = name
|
53
|
-
self._children: List[
|
52
|
+
self._children: List[Component] = []
|
54
53
|
self._props_use_name: Set[str] = set()
|
55
54
|
|
56
55
|
def _has_props_use(self):
|
instaui/components/vfor.py
CHANGED
@@ -60,7 +60,7 @@ class VFor(Component, Generic[_T]):
|
|
60
60
|
def __enter__(self) -> _T:
|
61
61
|
self.__scope = self.__scope_manager.__enter__()
|
62
62
|
super().__enter__()
|
63
|
-
return VForItem(self).proxy
|
63
|
+
return VForItem(self).proxy # type: ignore
|
64
64
|
|
65
65
|
def __exit__(self, *_) -> None:
|
66
66
|
self.__scope_manager.__exit__(*_)
|
@@ -0,0 +1,16 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
from dataclasses import dataclass, field
|
3
|
+
from pathlib import Path
|
4
|
+
from typing import List, Optional
|
5
|
+
|
6
|
+
_TTagName = str
|
7
|
+
|
8
|
+
|
9
|
+
@dataclass(frozen=True)
|
10
|
+
class ComponentDependencyInfo:
|
11
|
+
tag_name: _TTagName = field(hash=True)
|
12
|
+
esm: Path = field(hash=False)
|
13
|
+
externals: Optional[List[Path]] = field(
|
14
|
+
default_factory=list, compare=False, hash=False
|
15
|
+
)
|
16
|
+
css: List[Path] = field(default_factory=list, compare=False, hash=False)
|
@@ -0,0 +1,28 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
from dataclasses import dataclass, field
|
3
|
+
from pathlib import Path
|
4
|
+
from typing import List, Optional
|
5
|
+
from instaui.runtime._app import get_app_slot
|
6
|
+
|
7
|
+
|
8
|
+
@dataclass(frozen=True)
|
9
|
+
class PluginDependencyInfo:
|
10
|
+
name: str = field(hash=True)
|
11
|
+
esm: Path = field(hash=False)
|
12
|
+
externals: Optional[List[Path]] = field(
|
13
|
+
default_factory=list, compare=False, hash=False
|
14
|
+
)
|
15
|
+
css: List[Path] = field(default_factory=list, compare=False, hash=False)
|
16
|
+
|
17
|
+
|
18
|
+
def register_plugin(
|
19
|
+
name: str,
|
20
|
+
esm: Path,
|
21
|
+
*,
|
22
|
+
externals: Optional[List[Path]] = None,
|
23
|
+
css: Optional[List[Path]] = None,
|
24
|
+
):
|
25
|
+
info = PluginDependencyInfo(f"plugin/{name}", esm, externals or [], css or [])
|
26
|
+
|
27
|
+
get_app_slot().use_plugin_dependency(info)
|
28
|
+
return info
|
@@ -0,0 +1,21 @@
|
|
1
|
+
from fastapi import FastAPI
|
2
|
+
from fastapi.responses import FileResponse
|
3
|
+
|
4
|
+
from instaui.fastapi_server import resource
|
5
|
+
|
6
|
+
|
7
|
+
URL = f"{resource.URL}/{{hash_part:path}}"
|
8
|
+
|
9
|
+
|
10
|
+
def create_router(app: FastAPI):
|
11
|
+
_dependency_handler(app)
|
12
|
+
|
13
|
+
|
14
|
+
def _dependency_handler(app: FastAPI):
|
15
|
+
@app.get(URL)
|
16
|
+
def _(hash_part: str) -> FileResponse:
|
17
|
+
local_file = resource.get_by_hash(hash_part)
|
18
|
+
|
19
|
+
return FileResponse(
|
20
|
+
local_file, headers={"Cache-Control": "public, max-age=3600"}
|
21
|
+
)
|
@@ -0,0 +1,35 @@
|
|
1
|
+
from pathlib import Path
|
2
|
+
from typing import Dict
|
3
|
+
from urllib.parse import quote as urllib_quote
|
4
|
+
from instaui.systems import file_system
|
5
|
+
from instaui.version import __version__ as _INSTA_VERSION
|
6
|
+
|
7
|
+
URL = f"/_instaui_{_INSTA_VERSION}/resource"
|
8
|
+
_THashPart = str
|
9
|
+
_HASH_PART_MAP: Dict[_THashPart, Path] = {}
|
10
|
+
_FILE_URL_MAP: Dict[Path, _THashPart] = {}
|
11
|
+
|
12
|
+
|
13
|
+
def get_by_hash(hash_part: str) -> Path:
|
14
|
+
return _HASH_PART_MAP[hash_part]
|
15
|
+
|
16
|
+
|
17
|
+
def record_resource(path: Path):
|
18
|
+
if path in _FILE_URL_MAP:
|
19
|
+
return _FILE_URL_MAP[path]
|
20
|
+
|
21
|
+
hash_part = _generate_hash_part(path)
|
22
|
+
_HASH_PART_MAP[hash_part] = path
|
23
|
+
url = f"{URL}/{hash_part}"
|
24
|
+
_FILE_URL_MAP[path] = url
|
25
|
+
return url
|
26
|
+
|
27
|
+
|
28
|
+
def generate_static_url(file_path: Path):
|
29
|
+
return urllib_quote(f"{URL}/{_generate_hash_part(file_path)}")
|
30
|
+
|
31
|
+
|
32
|
+
def _generate_hash_part(file_path: Path):
|
33
|
+
file_path = Path(file_path).resolve()
|
34
|
+
hash_name = file_system.generate_hash_name_from_path(file_path)
|
35
|
+
return f"{hash_name}/{file_path.name}"
|
instaui/fastapi_server/server.py
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
from __future__ import annotations
|
2
|
+
from contextlib import contextmanager
|
2
3
|
import inspect
|
3
4
|
import os
|
4
5
|
import multiprocessing
|
@@ -8,29 +9,36 @@ import __main__
|
|
8
9
|
|
9
10
|
from fastapi import FastAPI
|
10
11
|
from fastapi import Request
|
11
|
-
from fastapi.responses import
|
12
|
-
from fastapi.staticfiles import StaticFiles
|
12
|
+
from fastapi.responses import HTMLResponse
|
13
13
|
import uvicorn
|
14
14
|
from uvicorn.supervisors import ChangeReload
|
15
|
+
import itertools
|
15
16
|
|
16
|
-
from instaui.html_tools import
|
17
|
+
from instaui.html_tools import to_config_data
|
17
18
|
from instaui.launch_collector import get_launch_collector
|
18
19
|
from instaui.page_info import PageInfo
|
19
|
-
|
20
|
-
from instaui.systems import file_system
|
20
|
+
|
21
21
|
from instaui import consts
|
22
|
-
from instaui.runtime._app import get_app_slot
|
22
|
+
from instaui.runtime._app import get_app_slot, get_default_app_slot
|
23
|
+
from instaui.runtime.dataclass import JsLink, VueAppComponent
|
23
24
|
from instaui.template import web_template
|
24
|
-
|
25
|
+
|
26
|
+
|
27
|
+
from . import dependency_router
|
25
28
|
from . import event_router
|
26
29
|
from . import watch_router
|
27
30
|
from . import debug_mode_router
|
28
31
|
from .middlewares import RequestContextMiddleware
|
29
32
|
from ._uvicorn import UvicornServer
|
30
|
-
|
33
|
+
from . import resource
|
31
34
|
|
32
35
|
APP_IMPORT_STRING = "instaui.fastapi_server.server:Server._instance.app"
|
33
36
|
|
37
|
+
VUE_JS_HASH_LINK = resource.record_resource(consts.VUE_ES_JS_PATH)
|
38
|
+
INSTAUI_JS_HASH_LINK = resource.record_resource(consts.APP_ES_JS_PATH)
|
39
|
+
APP_CSS_LINK = resource.record_resource(consts.APP_CSS_PATH)
|
40
|
+
TAILWIND_JS_HASH_LINK = resource.record_resource(consts.TAILWIND_JS_PATH)
|
41
|
+
|
34
42
|
|
35
43
|
class Server:
|
36
44
|
_instance: Optional[Server] = None
|
@@ -44,13 +52,11 @@ class Server:
|
|
44
52
|
def __init__(self):
|
45
53
|
self.app = FastAPI()
|
46
54
|
self.app.add_middleware(RequestContextMiddleware)
|
47
|
-
|
55
|
+
dependency_router.create_router(self.app)
|
48
56
|
event_router.create_router(self.app)
|
49
57
|
watch_router.create_router(self.app)
|
50
58
|
debug_mode_router.create_router(self.app)
|
51
59
|
|
52
|
-
self._static_dir_url = _add_static_dir(self.app)
|
53
|
-
|
54
60
|
for page_info in get_launch_collector()._page_router.values():
|
55
61
|
self.register_page(page_info)
|
56
62
|
|
@@ -61,125 +67,134 @@ class Server:
|
|
61
67
|
|
62
68
|
self._remove_route(info.path)
|
63
69
|
|
64
|
-
|
65
|
-
config_handler.register_handler(key, info.func)
|
66
|
-
config_fetch_url = (
|
67
|
-
config_handler.ASYNC_URL if is_async else config_handler.SYNC_URL
|
68
|
-
)
|
70
|
+
if is_async:
|
69
71
|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
config_fetch_url=config_fetch_url,
|
82
|
-
config_fetch_key=key,
|
83
|
-
query_path=info.path,
|
84
|
-
request=request,
|
85
|
-
page_loadding_json=page_loadding_json,
|
86
|
-
)
|
87
|
-
response = HTMLResponse(html)
|
88
|
-
return response
|
72
|
+
@self.app.get(info.path)
|
73
|
+
async def _(request: Request):
|
74
|
+
self._update_page_info(request, info)
|
75
|
+
with _execute_request_lifespans():
|
76
|
+
await info.func()
|
77
|
+
html = self._to_web_html(
|
78
|
+
page_info=info,
|
79
|
+
request=request,
|
80
|
+
)
|
81
|
+
|
82
|
+
return HTMLResponse(html)
|
89
83
|
|
90
|
-
|
84
|
+
else:
|
85
|
+
|
86
|
+
@self.app.get(info.path)
|
87
|
+
def _(request: Request):
|
88
|
+
self._update_page_info(request, info)
|
89
|
+
with _execute_request_lifespans():
|
90
|
+
info.func()
|
91
|
+
html = self._to_web_html(
|
92
|
+
page_info=info,
|
93
|
+
request=request,
|
94
|
+
)
|
95
|
+
|
96
|
+
return HTMLResponse(html)
|
91
97
|
|
92
98
|
def _to_web_html(
|
93
99
|
self,
|
94
100
|
*,
|
95
101
|
page_info: PageInfo,
|
96
|
-
query_path: str,
|
97
|
-
config_json: Optional[str] = None,
|
98
|
-
config_fetch_url: Optional[str] = None,
|
99
|
-
config_fetch_key: Optional[str] = None,
|
100
|
-
page_loadding_json: Optional[str] = None,
|
101
102
|
request: Request,
|
102
103
|
):
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
104
|
+
config_data = to_config_data()
|
105
|
+
|
106
|
+
model = web_template.WebTemplateModel(
|
107
|
+
vue_js_link=VUE_JS_HASH_LINK,
|
108
|
+
instaui_js_link=INSTAUI_JS_HASH_LINK,
|
109
|
+
css_links=[
|
110
|
+
APP_CSS_LINK,
|
111
|
+
],
|
112
|
+
config_dict=config_data,
|
109
113
|
)
|
110
114
|
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
+
system_slot = get_app_slot()
|
116
|
+
default_app_slot = get_default_app_slot()
|
117
|
+
html_resource = system_slot._html_resource
|
118
|
+
default_html_resource = default_app_slot._html_resource
|
115
119
|
|
116
|
-
if html_resource.use_tailwind:
|
117
|
-
|
118
|
-
|
120
|
+
if html_resource.use_tailwind is None:
|
121
|
+
if default_html_resource.use_tailwind:
|
122
|
+
model.js_links.append(JsLink(TAILWIND_JS_HASH_LINK))
|
123
|
+
else:
|
124
|
+
if html_resource.use_tailwind:
|
125
|
+
model.js_links.append(JsLink(TAILWIND_JS_HASH_LINK))
|
119
126
|
|
120
127
|
# register custom components
|
121
|
-
|
122
|
-
for component in system_slot._js_components:
|
128
|
+
for component in system_slot._component_dependencies:
|
123
129
|
if not component.esm:
|
124
130
|
continue
|
125
|
-
|
126
|
-
|
131
|
+
|
132
|
+
model.vue_app_component.append(
|
133
|
+
VueAppComponent(
|
134
|
+
name=component.tag_name,
|
135
|
+
url=resource.record_resource(component.esm),
|
136
|
+
)
|
137
|
+
)
|
127
138
|
|
128
139
|
if component.css:
|
129
140
|
for css_link in component.css:
|
130
|
-
|
141
|
+
model.css_links.append(resource.record_resource(css_link))
|
131
142
|
|
132
143
|
# register custom plugins
|
133
|
-
for plugin in
|
144
|
+
for plugin in set(
|
145
|
+
itertools.chain(
|
146
|
+
system_slot._plugin_dependencies, default_app_slot._plugin_dependencies
|
147
|
+
)
|
148
|
+
):
|
134
149
|
if not plugin.esm:
|
135
150
|
continue
|
136
|
-
|
137
|
-
|
151
|
+
|
152
|
+
model.vue_app_use.append(plugin.name)
|
153
|
+
|
154
|
+
model.add_extra_import_map(
|
155
|
+
plugin.name, resource.record_resource(plugin.esm)
|
156
|
+
)
|
138
157
|
|
139
158
|
if plugin.css:
|
140
159
|
for css_link in plugin.css:
|
141
|
-
|
160
|
+
model.css_links.append(resource.record_resource(css_link))
|
142
161
|
|
143
162
|
# css file link to web static link
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
163
|
+
for link, attrs in itertools.chain(
|
164
|
+
html_resource._css_links.items(), default_html_resource._css_links.items()
|
165
|
+
):
|
166
|
+
if isinstance(link, Path):
|
167
|
+
model.css_links.append(resource.record_resource(link))
|
148
168
|
|
149
169
|
# js file link to web static link
|
150
|
-
for info in
|
170
|
+
for info in itertools.chain(
|
171
|
+
html_resource._js_links, default_html_resource._js_links
|
172
|
+
):
|
151
173
|
if isinstance(info.link, Path):
|
152
|
-
|
174
|
+
model.js_links.append(JsLink((resource.record_resource(info.link))))
|
175
|
+
|
176
|
+
for js_code in itertools.chain(
|
177
|
+
html_resource._script_tags, default_html_resource._script_tags
|
178
|
+
):
|
179
|
+
model.script_tags.append(js_code)
|
180
|
+
|
181
|
+
for sylte_code in itertools.chain(
|
182
|
+
html_resource._style_tags, default_html_resource._style_tags
|
183
|
+
):
|
184
|
+
model.style_tags.append(sylte_code)
|
153
185
|
|
154
|
-
prefix = request.headers.get(
|
186
|
+
model.prefix = request.headers.get(
|
155
187
|
"X-Forwarded-Prefix", request.scope.get("root_path", "")
|
156
188
|
)
|
157
189
|
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
query_path_params=str(request.path_params),
|
163
|
-
query_params=dict(request.query_params),
|
164
|
-
query_path=query_path,
|
165
|
-
page_loadding_json=page_loadding_json,
|
166
|
-
prefix=prefix,
|
167
|
-
)
|
168
|
-
get_app_slot().reset_html_resource()
|
169
|
-
return result
|
170
|
-
|
171
|
-
def add_static_file_route(self, local_file: Path) -> str:
|
172
|
-
path = file_system.generate_static_url_from_file_path(local_file)
|
173
|
-
if path in self._registered_static_routes:
|
174
|
-
return path
|
175
|
-
|
176
|
-
@self.app.get(path)
|
177
|
-
def _() -> FileResponse:
|
178
|
-
return FileResponse(
|
179
|
-
local_file, headers={"Cache-Control": "public, max-age=3600"}
|
180
|
-
)
|
190
|
+
return web_template.render_web_html(model)
|
191
|
+
|
192
|
+
def _update_page_info(self, request: Request, page_info: PageInfo):
|
193
|
+
app = get_app_slot()
|
181
194
|
|
182
|
-
|
195
|
+
app._page_path = page_info.path
|
196
|
+
app._page_params = request.path_params
|
197
|
+
app._query_params = dict(request.query_params)
|
183
198
|
|
184
199
|
def _remove_route(self, path: str) -> None:
|
185
200
|
self.app.routes[:] = [
|
@@ -236,11 +251,20 @@ class Server:
|
|
236
251
|
assert isinstance(app, FastAPI), "app must be a FastAPI instance"
|
237
252
|
|
238
253
|
|
239
|
-
def _add_static_dir(app: FastAPI):
|
240
|
-
url = file_system.generate_static_url_from_file_path(consts._STATIC_DIR)
|
241
|
-
app.mount(url, StaticFiles(directory=consts._STATIC_DIR))
|
242
|
-
return url
|
243
|
-
|
244
|
-
|
245
254
|
def _split_args(args: str):
|
246
255
|
return [a.strip() for a in args.split(",")]
|
256
|
+
|
257
|
+
|
258
|
+
@contextmanager
|
259
|
+
def _execute_request_lifespans():
|
260
|
+
events = [iter(event()) for event in get_launch_collector().page_request_lifespans]
|
261
|
+
for event in events:
|
262
|
+
next(event)
|
263
|
+
|
264
|
+
yield
|
265
|
+
|
266
|
+
for event in events:
|
267
|
+
try:
|
268
|
+
next(event)
|
269
|
+
except StopIteration:
|
270
|
+
pass
|