instaui 0.1.4__py3-none-any.whl → 0.1.5__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.
Files changed (82) hide show
  1. instaui/components/echarts/echarts.js +128 -0
  2. instaui/components/echarts/echarts.py +194 -0
  3. instaui/components/echarts/static/echarts.esm.min.js +45 -0
  4. instaui/components/element.py +50 -4
  5. instaui/components/html/__init__.py +30 -19
  6. instaui/components/html/_preset.py +4 -0
  7. instaui/components/html/heading.py +51 -0
  8. instaui/components/html/range.py +3 -0
  9. instaui/components/html/select.py +13 -31
  10. instaui/components/html/table.py +36 -0
  11. instaui/components/markdown/static/marked.esm.js +0 -1
  12. instaui/components/shiki_code/shiki_code.js +126 -0
  13. instaui/components/shiki_code/shiki_code.py +99 -0
  14. instaui/components/shiki_code/static/langs/css.mjs +5 -0
  15. instaui/components/shiki_code/static/langs/markdown.mjs +5 -0
  16. instaui/components/shiki_code/static/langs/python.mjs +5 -0
  17. instaui/components/shiki_code/static/langs/shell.mjs +2 -0
  18. instaui/components/shiki_code/static/langs/shellscript.mjs +5 -0
  19. instaui/components/shiki_code/static/shiki-core.js +5784 -0
  20. instaui/components/shiki_code/static/shiki-style.css +175 -0
  21. instaui/components/shiki_code/static/shiki-transformers.js +461 -0
  22. instaui/components/shiki_code/static/themes/vitesse-dark.mjs +2 -0
  23. instaui/components/shiki_code/static/themes/vitesse-light.mjs +2 -0
  24. instaui/components/value_element.py +7 -3
  25. instaui/consts.py +2 -1
  26. instaui/daisyui/__init__.py +8 -2
  27. instaui/daisyui/_index.py +5 -0
  28. instaui/daisyui/table.py +35 -0
  29. instaui/event/js_event.py +1 -0
  30. instaui/event/web_event.py +6 -7
  31. instaui/fastapi_server/server.py +4 -12
  32. instaui/handlers/event_handler.py +3 -1
  33. instaui/handlers/watch_handler.py +4 -0
  34. instaui/html_tools.py +40 -2
  35. instaui/runtime/_app.py +37 -3
  36. instaui/runtime/_link_manager.py +89 -0
  37. instaui/runtime/resource.py +19 -9
  38. instaui/shadcn_classless/_index.py +42 -0
  39. instaui/shadcn_classless/static/shadcn-classless.css +403 -0
  40. instaui/static/insta-ui.css +1 -1
  41. instaui/static/insta-ui.esm-browser.prod.js +1314 -1253
  42. instaui/static/insta-ui.js.map +1 -1
  43. instaui/static/instaui-tools-browser.js +511 -0
  44. instaui/static/templates/webview.html +78 -0
  45. instaui/tailwind/__init__.py +6 -0
  46. instaui/tailwind/_index.py +24 -0
  47. instaui/{static/tailwindcss.min.js → tailwind/static/tailwindcss-v3.min.js} +62 -62
  48. instaui/tailwind/static/tailwindcss-v4.min.js +8 -0
  49. instaui/template/_utils.py +23 -0
  50. instaui/template/webview_template.py +50 -0
  51. instaui/ui/__init__.py +8 -2
  52. instaui/ui/__init__.pyi +7 -1
  53. instaui/vars/event_context.py +4 -0
  54. instaui/vars/web_computed.py +30 -30
  55. instaui/watch/web_watch.py +5 -6
  56. instaui/webview/__init__.py +1 -0
  57. instaui/webview/_utils.py +8 -0
  58. instaui/webview/api.py +72 -0
  59. instaui/webview/func.py +114 -0
  60. instaui/webview/index.py +162 -0
  61. instaui/webview/resource.py +172 -0
  62. instaui/zero/func.py +19 -12
  63. instaui/zero/scope.py +46 -28
  64. {instaui-0.1.4.dist-info → instaui-0.1.5.dist-info}/METADATA +4 -1
  65. {instaui-0.1.4.dist-info → instaui-0.1.5.dist-info}/RECORD +67 -47
  66. instaui/components/highlight_code/code.js +0 -63
  67. instaui/components/highlight_code/code.py +0 -117
  68. instaui/components/highlight_code/static/core.min.js +0 -307
  69. instaui/components/highlight_code/static/languages/css.min.js +0 -31
  70. instaui/components/highlight_code/static/languages/javascript.min.js +0 -81
  71. instaui/components/highlight_code/static/languages/json.min.js +0 -8
  72. instaui/components/highlight_code/static/languages/python-repl.min.js +0 -5
  73. instaui/components/highlight_code/static/languages/python.min.js +0 -42
  74. instaui/components/highlight_code/static/languages/shell.min.js +0 -5
  75. instaui/components/highlight_code/static/styles/default.min.css +0 -9
  76. instaui/components/highlight_code/static/styles/github-dark-dimmed.min.css +0 -9
  77. instaui/components/highlight_code/static/styles/github-dark.min.css +0 -10
  78. instaui/components/highlight_code/static/styles/github.min.css +0 -10
  79. instaui/handlers/computed_handler.py +0 -42
  80. instaui/handlers/config_handler.py +0 -13
  81. {instaui-0.1.4.dist-info → instaui-0.1.5.dist-info}/LICENSE +0 -0
  82. {instaui-0.1.4.dist-info → instaui-0.1.5.dist-info}/WHEEL +0 -0
@@ -0,0 +1,23 @@
1
+ from __future__ import annotations
2
+ import typing
3
+ from pathlib import Path
4
+ from urllib.parse import quote
5
+ import base64
6
+
7
+
8
+ _JS_PREFIX = "data:text/javascript;charset=utf-8"
9
+ _CSS_PREFIX = "data:text/css;charset=utf-8"
10
+ _ICON_PREFIX = "data:image/x-icon;base64"
11
+
12
+
13
+ def normalize_path_to_dataurl(path: typing.Union[str, Path], prefix: str):
14
+ if isinstance(path, Path):
15
+ path = path.read_text(encoding="utf-8")
16
+
17
+ return f"{prefix},{quote(path)}"
18
+
19
+
20
+ def normalize_path_to_base64_url(path: typing.Optional[Path], prefix: str):
21
+ if path is None:
22
+ return None
23
+ return f"{prefix},{base64.b64encode(path.read_bytes()).decode('utf-8')}"
@@ -0,0 +1,50 @@
1
+ from __future__ import annotations
2
+ import typing
3
+ from pathlib import Path
4
+ from dataclasses import dataclass, field
5
+ from instaui.common.jsonable import dumps
6
+ from instaui.runtime.dataclass import JsLink
7
+ from .env import env
8
+
9
+
10
+ _html_template = env.get_template("webview.html")
11
+
12
+
13
+ @dataclass(frozen=True)
14
+ class WebViewVueAppComponent:
15
+ name: str
16
+ url: str
17
+
18
+
19
+ @dataclass
20
+ class WebViewTemplateModel:
21
+ vue_js_code: str
22
+ instaui_js_code: str
23
+ config_dict: typing.Dict[str, typing.Any] = field(default_factory=dict)
24
+ extra_import_maps: typing.Dict[str, str] = field(default_factory=dict)
25
+ css_links: typing.List[str] = field(default_factory=list)
26
+ style_tags: typing.List[str] = field(default_factory=list)
27
+ js_links: typing.List[str] = field(default_factory=list)
28
+ script_tags: typing.List[str] = field(default_factory=list)
29
+ vue_app_use: typing.List[str] = field(default_factory=list)
30
+ vue_app_component: typing.List[WebViewVueAppComponent] = field(default_factory=list)
31
+ title: typing.Optional[str] = None
32
+ favicon_url: typing.Optional[str] = None
33
+ on_app_mounted: typing.Optional[typing.Callable] = None
34
+
35
+ def add_extra_import_map(self, name: str, code: str):
36
+ self.extra_import_maps[name] = code
37
+
38
+ @property
39
+ def import_maps_string(self):
40
+ data = {
41
+ **self.extra_import_maps,
42
+ "vue": self.vue_js_code,
43
+ "instaui": self.instaui_js_code,
44
+ }
45
+
46
+ return dumps(data)
47
+
48
+
49
+ def render_wbeview_html(model: WebViewTemplateModel) -> str:
50
+ return _html_template.render(model=model)
instaui/ui/__init__.py CHANGED
@@ -61,8 +61,11 @@ __all__ = [
61
61
  "str_format",
62
62
  "url_location",
63
63
  "on_page_request_lifespan",
64
+ "webview",
64
65
  "code",
65
66
  "markdown",
67
+ "echarts",
68
+ "use_shadcn_classless",
66
69
  ]
67
70
 
68
71
  # -- static imports
@@ -126,5 +129,8 @@ from .events import on_page_request_lifespan
126
129
 
127
130
  # -- dynamic imports
128
131
  from instaui.systems.module_system import LazyModule
129
- code = LazyModule('instaui.components.highlight_code.code', 'Code')
130
- markdown = LazyModule('instaui.components.markdown.markdown', 'Markdown')
132
+ code = LazyModule('instaui.components.shiki_code.shiki_code', 'Code')
133
+ markdown = LazyModule('instaui.components.markdown.markdown', 'Markdown')
134
+ webview = LazyModule('instaui.webview', 'WebviewWrapper')
135
+ echarts = LazyModule('instaui.components.echarts.echarts', 'ECharts')
136
+ use_shadcn_classless = LazyModule('instaui.shadcn_classless._index', 'use_shadcn_classless')
instaui/ui/__init__.pyi CHANGED
@@ -61,8 +61,11 @@ __all__ = [
61
61
  "str_format",
62
62
  "url_location",
63
63
  "on_page_request_lifespan",
64
+ "webview",
64
65
  "code",
65
66
  "markdown",
67
+ "echarts",
68
+ "use_shadcn_classless",
66
69
  ]
67
70
 
68
71
  # -- static imports
@@ -125,5 +128,8 @@ from instaui.ui_functions.ui_types import TBindable, is_bindable
125
128
  from .events import on_page_request_lifespan
126
129
 
127
130
  # -- dynamic imports
128
- from instaui.components.highlight_code.code import Code as code
131
+ from instaui.components.shiki_code.shiki_code import Code as code
129
132
  from instaui.components.markdown.markdown import Markdown as markdown
133
+ from instaui.webview import WebviewWrapper as webview
134
+ from instaui.components.echarts.echarts import ECharts as echarts
135
+ from instaui.shadcn_classless._index import use_shadcn_classless
@@ -30,6 +30,10 @@ class EventContext(Jsonable, CanInputMixin):
30
30
  def e():
31
31
  return EventContext(":e => e")
32
32
 
33
+ @staticmethod
34
+ def target_value():
35
+ return EventContext(":e => e.target.value")
36
+
33
37
 
34
38
  class DatasetEventContext(Jsonable, CanInputMixin):
35
39
  def __init__(self, event_context: EventContext) -> None:
@@ -24,6 +24,9 @@ from instaui.vars.mixin_types.observable import ObservableMixin
24
24
  from instaui.vars.mixin_types.common_type import TObservableInput
25
25
  from instaui._helper import observable_helper
26
26
 
27
+ _SYNC_TYPE = "sync"
28
+ _ASYNC_TYPE = "async"
29
+
27
30
  P = ParamSpec("P")
28
31
  R = TypeVar("R")
29
32
 
@@ -70,47 +73,44 @@ class WebComputed(
70
73
 
71
74
  app = get_app_slot()
72
75
 
73
- if app.mode == "web":
74
- hkey = watch_handler.create_handler_key(
75
- page_path=app.page_path,
76
- handler=self._fn,
77
- )
76
+ hkey = watch_handler.create_handler_key(
77
+ page_path=app.page_path,
78
+ handler=self._fn,
79
+ )
78
80
 
79
- watch_handler.register_handler(hkey, self._fn, len(self._outputs) + 1)
81
+ watch_handler.register_handler(hkey, self._fn, len(self._outputs) + 1)
80
82
 
81
- url = (
82
- watch_handler.ASYNC_URL
83
- if inspect.iscoroutinefunction(self._fn)
84
- else watch_handler.SYNC_URL
85
- )
83
+ # if app.mode == "web":
86
84
 
87
- data["id"] = self._id
88
- data["sid"] = self._sid
89
- data["type"] = self.VAR_TYPE
85
+ data["id"] = self._id
86
+ data["sid"] = self._sid
87
+ data["type"] = self.VAR_TYPE
90
88
 
91
- if self._inputs:
92
- data["inputs"] = self._inputs
89
+ if self._inputs:
90
+ data["inputs"] = self._inputs
93
91
 
94
- if self._outputs:
95
- data["outputs"] = self._outputs
92
+ if self._outputs:
93
+ data["outputs"] = self._outputs
96
94
 
97
- if sum(self._is_slient_inputs) > 0:
98
- data["slient"] = self._is_slient_inputs
95
+ if sum(self._is_slient_inputs) > 0:
96
+ data["slient"] = self._is_slient_inputs
99
97
 
100
- if sum(self._is_data) > 0:
101
- data["data"] = self._is_data
98
+ if sum(self._is_data) > 0:
99
+ data["data"] = self._is_data
102
100
 
103
- data["url"] = url
104
- data["key"] = hkey
105
- if self._init_value is not None:
106
- data["init"] = self._init_value
101
+ data["fType"] = (
102
+ _ASYNC_TYPE if inspect.iscoroutinefunction(self._fn) else _SYNC_TYPE
103
+ )
104
+ data["key"] = hkey
105
+ if self._init_value is not None:
106
+ data["init"] = self._init_value
107
107
 
108
- if self._evaluating:
109
- data["running"] = self._evaluating._to_output_config()
108
+ if self._evaluating:
109
+ data["running"] = self._evaluating._to_output_config()
110
110
 
111
- return data
111
+ return data
112
112
 
113
- return {}
113
+ # return {}
114
114
 
115
115
  def __to_binding_config(self):
116
116
  return {
@@ -13,6 +13,9 @@ from instaui.vars.mixin_types.py_binding import CanOutputMixin
13
13
  from instaui.vars.mixin_types.common_type import TObservableInput
14
14
  from instaui._helper import observable_helper
15
15
 
16
+ _SYNC_TYPE = "sync"
17
+ _ASYNC_TYPE = "async"
18
+
16
19
  P = ParamSpec("P")
17
20
  R = typing.TypeVar("R")
18
21
 
@@ -59,13 +62,9 @@ class WebWatch(Jsonable, typing.Generic[P, R]):
59
62
 
60
63
  watch_handler.register_handler(hkey, self._fn, len(self._outputs))
61
64
 
62
- url = (
63
- watch_handler.ASYNC_URL
64
- if inspect.iscoroutinefunction(self._fn)
65
- else watch_handler.SYNC_URL
65
+ data["fType"] = (
66
+ _ASYNC_TYPE if inspect.iscoroutinefunction(self._fn) else _SYNC_TYPE
66
67
  )
67
-
68
- data["url"] = url
69
68
  data["key"] = hkey
70
69
  if self._inputs:
71
70
  data["inputs"] = self._inputs
@@ -0,0 +1 @@
1
+ from .index import WebviewWrapper
@@ -0,0 +1,8 @@
1
+ from pathlib import Path
2
+ import shutil
3
+
4
+
5
+ def reset_dir(dir_path: Path):
6
+ if dir_path.exists():
7
+ shutil.rmtree(dir_path)
8
+ dir_path.mkdir(exist_ok=True)
instaui/webview/api.py ADDED
@@ -0,0 +1,72 @@
1
+ from typing import Any, Dict
2
+
3
+
4
+ from instaui.runtime._app import get_app_slot
5
+ from instaui.handlers import watch_handler
6
+ from instaui.handlers import event_handler
7
+ from instaui.skip import is_skip_output
8
+
9
+
10
+ class Api:
11
+ def watch_call(self, data: Dict):
12
+ hkey = data.pop("key")
13
+ handler_info = watch_handler.get_handler_info(hkey)
14
+ if handler_info is None:
15
+ return {"error": "watch handler not found"}
16
+
17
+ update_app_page_info(data)
18
+
19
+ result = handler_info.fn(
20
+ *handler_info.get_handler_args(_get_binds_from_data(data))
21
+ )
22
+ return response_data(handler_info.outputs_binding_count, result)
23
+
24
+ def event_call(self, data: Dict):
25
+ handler = event_handler.get_handler(data["hKey"])
26
+ if handler is None:
27
+ raise ValueError("event handler not found")
28
+
29
+ update_app_page_info(data)
30
+
31
+
32
+ args = [bind for bind in data.get("bind", [])]
33
+
34
+ result = handler.fn(*handler.get_handler_args(args))
35
+ return response_data(handler.outputs_binding_count, result)
36
+
37
+
38
+ def update_app_page_info(data: Dict):
39
+ app = get_app_slot()
40
+
41
+ page_info = data.get("page", {})
42
+ app._page_path = page_info["path"]
43
+
44
+ if "params" in page_info:
45
+ app._page_params = page_info["params"]
46
+
47
+ if "queryParams" in page_info:
48
+ app._query_params = page_info["queryParams"]
49
+
50
+
51
+ def _get_binds_from_data(data: Dict):
52
+ return data.get("input", [])
53
+
54
+
55
+ def response_data(outputs_binding_count: int, result: Any):
56
+ data = {}
57
+ if outputs_binding_count > 0:
58
+ if not isinstance(result, tuple):
59
+ result = [result]
60
+
61
+ result_infos = [(r, int(is_skip_output(r))) for r in result]
62
+
63
+ if len(result_infos) == 1 and result_infos[0][1] == 1:
64
+ return data
65
+
66
+ data["values"] = [0 if info[1] == 1 else info[0] for info in result_infos]
67
+ skips = [info[1] for info in result_infos]
68
+
69
+ if sum(skips) > 0:
70
+ data["skips"] = skips
71
+
72
+ return data
@@ -0,0 +1,114 @@
1
+ from __future__ import annotations
2
+ import itertools
3
+ from pathlib import Path
4
+ import instaui.consts as consts
5
+ from instaui.runtime._app import get_app_slot, get_default_app_slot
6
+ from instaui.template import render_zero_html
7
+ from instaui.template import zero_template
8
+ from instaui.html_tools import to_config_data
9
+ from instaui.runtime.dataclass import JsLink
10
+ from instaui.runtime.resource import HtmlResource
11
+
12
+
13
+ def get_template_model():
14
+ system_slot = get_app_slot()
15
+
16
+ merge_global_resources = (system_slot.meta or {}).get(
17
+ "merge_global_resources", True
18
+ )
19
+
20
+ default_app_slot = get_default_app_slot()
21
+ html_resource = system_slot._html_resource
22
+ default_html_resource = (
23
+ default_app_slot._html_resource
24
+ if merge_global_resources
25
+ else _empty_html_resource()
26
+ )
27
+
28
+ config_data = to_config_data()
29
+
30
+ model = zero_template.ZeroTemplateModel(
31
+ vue_js_code=consts.VUE_ES_JS_PATH,
32
+ instaui_js_code=consts.APP_ES_JS_PATH,
33
+ css_links=[
34
+ consts.APP_CSS_PATH,
35
+ ],
36
+ config_dict=config_data,
37
+ favicon=html_resource.favicon
38
+ or default_html_resource.favicon
39
+ or consts.FAVICON_PATH,
40
+ title=html_resource.title or default_html_resource.title or consts.PAGE_TITLE,
41
+ )
42
+
43
+ # register custom components
44
+ for component in system_slot._component_dependencies:
45
+ if not component.esm:
46
+ continue
47
+
48
+ model.vue_app_component.append(
49
+ zero_template.ZeroVueAppComponent(
50
+ name=component.tag_name,
51
+ url=component.esm,
52
+ )
53
+ )
54
+
55
+ if component.css:
56
+ for css_link in component.css:
57
+ model.css_links.append(css_link)
58
+
59
+ if component.externals:
60
+ for name, url in component.externals.items():
61
+ if url.is_file():
62
+ model.add_extra_import_map(name, url)
63
+
64
+ # register custom plugins
65
+ for plugin in set(
66
+ itertools.chain(
67
+ system_slot._plugin_dependencies, default_app_slot._plugin_dependencies
68
+ )
69
+ ):
70
+ if not plugin.esm:
71
+ continue
72
+
73
+ model.vue_app_use.append(plugin.name)
74
+
75
+ model.add_extra_import_map(plugin.name, plugin.esm)
76
+
77
+ if plugin.css:
78
+ for css_link in plugin.css:
79
+ model.css_links.append(css_link)
80
+
81
+ # css file link to web static link
82
+ for link in html_resource.get_valid_css_links(
83
+ default_html_resource._css_links_manager
84
+ ):
85
+ if isinstance(link, Path):
86
+ model.css_links.append(link)
87
+
88
+ # js file link to web static link
89
+ for info in html_resource.get_valid_js_links(
90
+ default_html_resource._js_links_manager
91
+ ):
92
+ if isinstance(info.link, Path):
93
+ model.js_links.append(JsLink(info.link))
94
+
95
+ for js_code in itertools.chain(
96
+ html_resource._script_tags, default_html_resource._script_tags
97
+ ):
98
+ model.script_tags.append(js_code)
99
+
100
+ for sylte_code in itertools.chain(
101
+ html_resource._style_tags, default_html_resource._style_tags
102
+ ):
103
+ model.style_tags.append(sylte_code)
104
+
105
+ return model
106
+
107
+
108
+ def to_html_str():
109
+ model = get_template_model()
110
+ return render_zero_html(model)
111
+
112
+
113
+ def _empty_html_resource():
114
+ return HtmlResource()
@@ -0,0 +1,162 @@
1
+ from __future__ import annotations
2
+ from contextlib import contextmanager
3
+ from pathlib import Path
4
+ import shutil
5
+ from typing import Any, Callable, Dict, Iterable, List, Optional, Union
6
+ from typing_extensions import TypedDict, Unpack
7
+ import webview
8
+ import webview.http as http
9
+ from webview.guilib import GUIType
10
+
11
+ from instaui.runtime._app import get_app_slot, new_app_slot, reset_app_slot
12
+ from instaui.launch_collector import get_launch_collector
13
+
14
+ from . import resource
15
+ from . import api
16
+ from . import _utils
17
+
18
+
19
+ class WebviewWrapper:
20
+ """Example usage:
21
+ .. code-block:: python
22
+ from instaui import ui
23
+
24
+ @ui.page("/")
25
+ def index_page():
26
+ ui.content("Hello, world!")
27
+
28
+ ui.webview().run()
29
+ """
30
+
31
+ def __init__(
32
+ self,
33
+ *,
34
+ assets_path: Union[str, Path] = "./webview_assets",
35
+ debug: bool = False,
36
+ auto_create_window: Union[bool, str] = "/",
37
+ on_app_mounted: Optional[Callable] = None,
38
+ ) -> None:
39
+ """Create a new webview wrapper.
40
+
41
+ Args:
42
+ assets_path (Union[str, Path], optional): Path to store assets. Defaults to "./webview_assets".
43
+ debug (bool, optional): Whether to run in debug mode. Defaults to False.
44
+ auto_create_window (Union[bool, str], optional): Whether to create a window automatically. If a string is provided, it will be used as the initial page URL. Defaults to "/".
45
+ testing (bool, optional): Whether to run in testing mode. Defaults to False.
46
+ """
47
+
48
+ self.assets_path = (
49
+ Path(self._get_assets_path(assets_path))
50
+ if isinstance(assets_path, str)
51
+ else assets_path
52
+ )
53
+ _utils.reset_dir(self.assets_path)
54
+ self.debug = debug
55
+ self.on_app_mounted = on_app_mounted
56
+
57
+ self._auto_create_window = auto_create_window
58
+
59
+ def create_window(
60
+ self,
61
+ page_url: str = "/",
62
+ ):
63
+ """Create a new window. Returns the window object of pywebview.
64
+
65
+ Args:
66
+ page_url (str, optional): Page URL to load. Defaults to "/".
67
+
68
+ """
69
+ launch_collector = get_launch_collector()
70
+ with _scope():
71
+ app = get_app_slot()
72
+ app._page_path = page_url
73
+ page_info = launch_collector._page_router[page_url]
74
+ page_info.func()
75
+
76
+ resource_info = resource.resource_to_assets(
77
+ page_url=page_url,
78
+ assets_path=self.assets_path,
79
+ on_app_mounted=self.on_app_mounted,
80
+ )
81
+
82
+ window = webview.create_window(
83
+ resource_info.title, resource_info.index_html_url, js_api=api.Api()
84
+ )
85
+
86
+ if self.on_app_mounted:
87
+
88
+ def on_app_mounted():
89
+ self.on_app_mounted(window) # type: ignore
90
+
91
+ window.expose(on_app_mounted)
92
+
93
+ return window
94
+
95
+ def run(self, **webview_start_args: Unpack[WebviewStartArgs]):
96
+ """Run the webview.
97
+
98
+ Args:
99
+ :param func: Function to invoke upon starting the GUI loop.
100
+ :param args: Function arguments. Can be either a single value or a tuple of
101
+ values.
102
+ :param localization: A dictionary with localized strings. Default strings
103
+ and their keys are defined in localization.py.
104
+ :param gui: Force a specific GUI. Allowed values are ``cef``, ``qt``,
105
+ ``gtk``, ``mshtml`` or ``edgechromium`` depending on a platform.
106
+ :param http_server: Enable built-in HTTP server. If enabled, local files
107
+ will be served using a local HTTP server on a random port. For each
108
+ window, a separate HTTP server is spawned. This option is ignored for
109
+ non-local URLs.
110
+ :param user_agent: Change user agent string.
111
+ :param private_mode: Enable private mode. In private mode, cookies and local storage are not preserved.
112
+ Default is True.
113
+ :param storage_path: Custom location for cookies and other website data
114
+ :param menu: List of menus to be included in the app menu
115
+ :param server: Server class. Defaults to BottleServer
116
+ :param server_args: Dictionary of arguments to pass through to the server instantiation
117
+ :param ssl: Enable SSL for local HTTP server. Default is False.
118
+ :param icon: Path to the icon file. Supported only on GTK/QT.
119
+ """
120
+
121
+ if self._auto_create_window:
122
+ self.create_window(
123
+ "/" if self._auto_create_window is True else self._auto_create_window
124
+ )
125
+
126
+ webview.start(**webview_start_args, debug=self.debug)
127
+
128
+ @staticmethod
129
+ def _get_assets_path(file: Union[str, Path]) -> Path:
130
+ if isinstance(file, str):
131
+ import inspect
132
+
133
+ frame = inspect.currentframe().f_back.f_back.f_back # type: ignore
134
+ assert frame is not None
135
+ script_file = inspect.getfile(frame)
136
+ file = Path(script_file).parent.joinpath(file)
137
+
138
+ return file
139
+
140
+
141
+ @contextmanager
142
+ def _scope():
143
+ token = new_app_slot("webview")
144
+ yield
145
+ reset_app_slot(token)
146
+
147
+
148
+ class WebviewStartArgs(TypedDict, total=False):
149
+ func: Union[Callable[..., None], None]
150
+ args: Union[Iterable[Any], None]
151
+ localization: Dict[str, str]
152
+ gui: Union[GUIType, None]
153
+ http_server: bool
154
+ http_port: Union[int, None]
155
+ user_agent: Union[str, None]
156
+ private_mode: bool
157
+ storage_path: Union[str, None]
158
+ menu: List[Any]
159
+ server: type[http.ServerType] # type: ignore
160
+ server_args: Dict[Any, Any]
161
+ ssl: bool
162
+ icon: Union[str, None]