instaui 0.1.0__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/__init__.py +9 -0
- instaui/_helper/observable_helper.py +35 -0
- instaui/boot_info.py +43 -0
- instaui/common/jsonable.py +37 -0
- instaui/components/__init__.py +0 -0
- instaui/components/column.py +18 -0
- instaui/components/component.py +47 -0
- instaui/components/content.py +34 -0
- instaui/components/directive.py +55 -0
- instaui/components/element.py +462 -0
- instaui/components/grid.py +80 -0
- instaui/components/html/__init__.py +36 -0
- instaui/components/html/_mixins.py +34 -0
- instaui/components/html/button.py +38 -0
- instaui/components/html/checkbox.py +42 -0
- instaui/components/html/date.py +28 -0
- instaui/components/html/div.py +7 -0
- instaui/components/html/form.py +7 -0
- instaui/components/html/input.py +28 -0
- instaui/components/html/label.py +21 -0
- instaui/components/html/li.py +17 -0
- instaui/components/html/link.py +31 -0
- instaui/components/html/number.py +34 -0
- instaui/components/html/paragraph.py +19 -0
- instaui/components/html/range.py +45 -0
- instaui/components/html/select.py +93 -0
- instaui/components/html/span.py +19 -0
- instaui/components/html/ul.py +20 -0
- instaui/components/match.py +106 -0
- instaui/components/row.py +19 -0
- instaui/components/slot.py +82 -0
- instaui/components/transition_group.py +9 -0
- instaui/components/value_element.py +48 -0
- instaui/components/vfor.py +140 -0
- instaui/components/vif.py +38 -0
- instaui/consts.py +18 -0
- instaui/dependencies/__init__.py +15 -0
- instaui/dependencies/component_registrar.py +82 -0
- instaui/dependencies/installer.py +5 -0
- instaui/event/event_mixin.py +12 -0
- instaui/event/js_event.py +57 -0
- instaui/event/web_event.py +108 -0
- instaui/experimental/__init__.py +4 -0
- instaui/experimental/debug.py +48 -0
- instaui/fastapi_server/_utils.py +42 -0
- instaui/fastapi_server/_uvicorn.py +37 -0
- instaui/fastapi_server/config_router.py +60 -0
- instaui/fastapi_server/debug_mode_router.py +61 -0
- instaui/fastapi_server/event_router.py +58 -0
- instaui/fastapi_server/middlewares.py +19 -0
- instaui/fastapi_server/request_context.py +19 -0
- instaui/fastapi_server/server.py +246 -0
- instaui/fastapi_server/watch_router.py +53 -0
- instaui/handlers/_utils.py +66 -0
- instaui/handlers/computed_handler.py +42 -0
- instaui/handlers/config_handler.py +13 -0
- instaui/handlers/event_handler.py +58 -0
- instaui/handlers/watch_handler.py +57 -0
- instaui/html_tools.py +139 -0
- instaui/inject.py +33 -0
- instaui/js/__init__.py +4 -0
- instaui/js/js_output.py +15 -0
- instaui/js/lambda_func.py +35 -0
- instaui/launch_collector.py +52 -0
- instaui/page_info.py +23 -0
- instaui/runtime/__init__.py +29 -0
- instaui/runtime/_app.py +206 -0
- instaui/runtime/_inner_helper.py +9 -0
- instaui/runtime/context.py +47 -0
- instaui/runtime/dataclass.py +30 -0
- instaui/runtime/resource.py +87 -0
- instaui/runtime/scope.py +107 -0
- instaui/runtime/ui_state_scope.py +15 -0
- instaui/settings/__init__.py +4 -0
- instaui/settings/__settings.py +13 -0
- instaui/skip.py +12 -0
- instaui/spa_router/__init__.py +26 -0
- instaui/spa_router/_components.py +35 -0
- instaui/spa_router/_file_base_utils.py +264 -0
- instaui/spa_router/_functions.py +122 -0
- instaui/spa_router/_install.py +11 -0
- instaui/spa_router/_route_model.py +139 -0
- instaui/spa_router/_router_box.py +40 -0
- instaui/spa_router/_router_output.py +22 -0
- instaui/spa_router/_router_param_var.py +51 -0
- instaui/spa_router/_types.py +4 -0
- instaui/spa_router/templates/page_routes +59 -0
- instaui/static/insta-ui.css +1 -0
- instaui/static/insta-ui.esm-browser.prod.js +3663 -0
- instaui/static/insta-ui.iife.js +29 -0
- instaui/static/insta-ui.iife.js.map +1 -0
- instaui/static/insta-ui.js.map +1 -0
- instaui/static/tailwindcss.min.js +62 -0
- instaui/static/templates/debug/sse.html +117 -0
- instaui/static/templates/web.html +118 -0
- instaui/static/templates/zero.html +55 -0
- instaui/static/vue.esm-browser.prod.js +9 -0
- instaui/static/vue.global.prod.js +9 -0
- instaui/static/vue.runtime.esm-browser.prod.js +5 -0
- instaui/systems/file_system.py +17 -0
- instaui/systems/func_system.py +104 -0
- instaui/systems/js_system.py +22 -0
- instaui/systems/pydantic_system.py +27 -0
- instaui/systems/string_system.py +10 -0
- instaui/template/__init__.py +4 -0
- instaui/template/env.py +7 -0
- instaui/template/web_template.py +55 -0
- instaui/template/zero_template.py +24 -0
- instaui/ui/__init__.py +121 -0
- instaui/ui/events.py +25 -0
- instaui/ui_functions/input_slient_data.py +16 -0
- instaui/ui_functions/server.py +13 -0
- instaui/ui_functions/str_format.py +36 -0
- instaui/ui_functions/ui_page.py +31 -0
- instaui/ui_functions/ui_types.py +13 -0
- instaui/ui_functions/url_location.py +33 -0
- instaui/vars/__init__.py +13 -0
- instaui/vars/_types.py +8 -0
- instaui/vars/_utils.py +12 -0
- instaui/vars/data.py +68 -0
- instaui/vars/element_ref.py +42 -0
- instaui/vars/event_context.py +45 -0
- instaui/vars/event_extend.py +0 -0
- instaui/vars/js_computed.py +95 -0
- instaui/vars/mixin_types/common_type.py +5 -0
- instaui/vars/mixin_types/element_binding.py +10 -0
- instaui/vars/mixin_types/observable.py +7 -0
- instaui/vars/mixin_types/pathable.py +14 -0
- instaui/vars/mixin_types/py_binding.py +13 -0
- instaui/vars/mixin_types/str_format_binding.py +8 -0
- instaui/vars/mixin_types/var_type.py +5 -0
- instaui/vars/path_var.py +89 -0
- instaui/vars/ref.py +103 -0
- instaui/vars/slot_prop.py +46 -0
- instaui/vars/state.py +82 -0
- instaui/vars/types.py +24 -0
- instaui/vars/vfor_item.py +204 -0
- instaui/vars/vue_computed.py +82 -0
- instaui/vars/web_computed.py +157 -0
- instaui/vars/web_view_computed.py +1 -0
- instaui/version.py +3 -0
- instaui/watch/_types.py +4 -0
- instaui/watch/_utils.py +3 -0
- instaui/watch/js_watch.py +74 -0
- instaui/watch/vue_watch.py +61 -0
- instaui/watch/web_watch.py +123 -0
- instaui/zero/__init__.py +3 -0
- instaui/zero/scope.py +9 -0
- instaui-0.1.0.dist-info/LICENSE +21 -0
- instaui-0.1.0.dist-info/METADATA +154 -0
- instaui-0.1.0.dist-info/RECORD +152 -0
- instaui-0.1.0.dist-info/WHEEL +4 -0
@@ -0,0 +1,157 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
import inspect
|
3
|
+
from typing import (
|
4
|
+
Any,
|
5
|
+
Callable,
|
6
|
+
Dict,
|
7
|
+
Generic,
|
8
|
+
Optional,
|
9
|
+
Sequence,
|
10
|
+
TypeVar,
|
11
|
+
)
|
12
|
+
from typing_extensions import ParamSpec
|
13
|
+
|
14
|
+
from instaui.common.jsonable import Jsonable
|
15
|
+
from instaui.runtime._app import get_app_slot, get_current_scope
|
16
|
+
from instaui.handlers import watch_handler
|
17
|
+
|
18
|
+
from instaui.vars.path_var import PathVar
|
19
|
+
from instaui.vars.mixin_types.py_binding import CanInputMixin, CanOutputMixin
|
20
|
+
from instaui.vars.mixin_types.element_binding import ElementBindingMixin
|
21
|
+
from instaui.vars.mixin_types.pathable import CanPathPropMixin
|
22
|
+
from instaui.vars.mixin_types.str_format_binding import StrFormatBindingMixin
|
23
|
+
from instaui.vars.mixin_types.observable import ObservableMixin
|
24
|
+
from instaui.vars.mixin_types.common_type import TObservableInput
|
25
|
+
from instaui._helper import observable_helper
|
26
|
+
|
27
|
+
P = ParamSpec("P")
|
28
|
+
R = TypeVar("R")
|
29
|
+
|
30
|
+
|
31
|
+
class WebComputed(
|
32
|
+
Jsonable,
|
33
|
+
PathVar,
|
34
|
+
CanInputMixin,
|
35
|
+
ObservableMixin,
|
36
|
+
CanPathPropMixin,
|
37
|
+
StrFormatBindingMixin,
|
38
|
+
ElementBindingMixin[R],
|
39
|
+
Generic[P, R],
|
40
|
+
):
|
41
|
+
VAR_TYPE = "webComputed"
|
42
|
+
|
43
|
+
def __init__(
|
44
|
+
self,
|
45
|
+
func: Callable[P, R],
|
46
|
+
inputs: Optional[Sequence[TObservableInput]] = None,
|
47
|
+
extend_outputs: Optional[Sequence[CanOutputMixin]] = None,
|
48
|
+
init_value: Optional[R] = None,
|
49
|
+
evaluating: Optional[CanOutputMixin] = None,
|
50
|
+
) -> None:
|
51
|
+
scope = get_current_scope()
|
52
|
+
|
53
|
+
self._sid = scope.id
|
54
|
+
self._id = scope.generate_vars_id()
|
55
|
+
get_current_scope().register_web_computed(self)
|
56
|
+
|
57
|
+
self._inputs, self._is_slient_inputs, self._is_data = (
|
58
|
+
observable_helper.analyze_observable_inputs(list(inputs or []))
|
59
|
+
)
|
60
|
+
self._outputs = [output._to_output_config() for output in extend_outputs or []]
|
61
|
+
self._fn = func
|
62
|
+
self._init_value = init_value
|
63
|
+
self._evaluating = evaluating
|
64
|
+
|
65
|
+
def __call__(self, *args: P.args, **kwargs: P.kwargs) -> R:
|
66
|
+
return self._fn(*args, **kwargs)
|
67
|
+
|
68
|
+
def _to_json_dict(self):
|
69
|
+
data = super()._to_json_dict()
|
70
|
+
|
71
|
+
app = get_app_slot()
|
72
|
+
|
73
|
+
if app.mode == "web":
|
74
|
+
hkey = watch_handler.create_handler_key(
|
75
|
+
page_path=app.page_path,
|
76
|
+
handler=self._fn,
|
77
|
+
)
|
78
|
+
|
79
|
+
watch_handler.register_handler(hkey, self._fn, len(self._outputs) + 1)
|
80
|
+
|
81
|
+
url = (
|
82
|
+
watch_handler.ASYNC_URL
|
83
|
+
if inspect.iscoroutinefunction(self._fn)
|
84
|
+
else watch_handler.SYNC_URL
|
85
|
+
)
|
86
|
+
|
87
|
+
data["id"] = self._id
|
88
|
+
data["sid"] = self._sid
|
89
|
+
data["type"] = self.VAR_TYPE
|
90
|
+
|
91
|
+
if self._inputs:
|
92
|
+
data["inputs"] = self._inputs
|
93
|
+
|
94
|
+
if self._outputs:
|
95
|
+
data["outputs"] = self._outputs
|
96
|
+
|
97
|
+
if sum(self._is_slient_inputs) > 0:
|
98
|
+
data["slient"] = self._is_slient_inputs
|
99
|
+
|
100
|
+
if sum(self._is_data) > 0:
|
101
|
+
data["data"] = self._is_data
|
102
|
+
|
103
|
+
data["url"] = url
|
104
|
+
data["key"] = hkey
|
105
|
+
if self._init_value is not None:
|
106
|
+
data["init"] = self._init_value
|
107
|
+
|
108
|
+
if self._evaluating:
|
109
|
+
data["running"] = self._evaluating._to_output_config()
|
110
|
+
|
111
|
+
return data
|
112
|
+
|
113
|
+
return {}
|
114
|
+
|
115
|
+
def __to_binding_config(self):
|
116
|
+
return {
|
117
|
+
"type": self.VAR_TYPE,
|
118
|
+
"id": self._id,
|
119
|
+
"sid": self._sid,
|
120
|
+
}
|
121
|
+
|
122
|
+
def _to_pathable_binding_config(self) -> Dict:
|
123
|
+
return self.__to_binding_config()
|
124
|
+
|
125
|
+
def _to_path_prop_binding_config(self) -> Dict:
|
126
|
+
return self.__to_binding_config()
|
127
|
+
|
128
|
+
def _to_input_config(self):
|
129
|
+
return self.__to_binding_config()
|
130
|
+
|
131
|
+
def _to_element_binding_config(self):
|
132
|
+
return self.__to_binding_config()
|
133
|
+
|
134
|
+
def _to_observable_config(self):
|
135
|
+
return self.__to_binding_config()
|
136
|
+
|
137
|
+
|
138
|
+
def web_computed(
|
139
|
+
*,
|
140
|
+
inputs: Optional[Sequence] = None,
|
141
|
+
extend_outputs: Optional[Sequence] = None,
|
142
|
+
init_value: Optional[Any] = None,
|
143
|
+
evaluating: Optional[Any] = None,
|
144
|
+
):
|
145
|
+
def wrapper(func: Callable[P, R]):
|
146
|
+
return WebComputed(
|
147
|
+
func,
|
148
|
+
inputs=inputs,
|
149
|
+
extend_outputs=extend_outputs,
|
150
|
+
init_value=init_value,
|
151
|
+
evaluating=evaluating,
|
152
|
+
)
|
153
|
+
|
154
|
+
return wrapper
|
155
|
+
|
156
|
+
|
157
|
+
TComputed = WebComputed
|
@@ -0,0 +1 @@
|
|
1
|
+
from __future__ import annotations
|
instaui/version.py
ADDED
instaui/watch/_types.py
ADDED
instaui/watch/_utils.py
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
import typing
|
2
|
+
from . import _types
|
3
|
+
from . import _utils
|
4
|
+
|
5
|
+
from instaui.common.jsonable import Jsonable
|
6
|
+
from instaui.runtime._app import get_current_scope
|
7
|
+
|
8
|
+
from instaui.vars.mixin_types.py_binding import CanOutputMixin
|
9
|
+
from instaui.vars.mixin_types.common_type import TObservableInput
|
10
|
+
from instaui._helper import observable_helper
|
11
|
+
|
12
|
+
|
13
|
+
class JsWatch(Jsonable):
|
14
|
+
def __init__(
|
15
|
+
self,
|
16
|
+
code: str,
|
17
|
+
inputs: typing.Optional[typing.Sequence[TObservableInput]] = None,
|
18
|
+
outputs: typing.Optional[typing.Sequence[CanOutputMixin]] = None,
|
19
|
+
immediate: bool = True,
|
20
|
+
deep: typing.Union[bool, int] = False,
|
21
|
+
once: bool = False,
|
22
|
+
flush: typing.Optional[_types.TFlush] = None,
|
23
|
+
) -> None:
|
24
|
+
get_current_scope().register_js_watch(self)
|
25
|
+
|
26
|
+
self.code = code
|
27
|
+
|
28
|
+
self._inputs, self._is_slient_inputs, self._is_data = (
|
29
|
+
observable_helper.analyze_observable_inputs(list(inputs or []))
|
30
|
+
)
|
31
|
+
self._outputs = [output._to_output_config() for output in outputs or []]
|
32
|
+
|
33
|
+
if immediate is not True:
|
34
|
+
self.immediate = immediate
|
35
|
+
|
36
|
+
if deep is not False:
|
37
|
+
_utils.assert_deep(deep)
|
38
|
+
self.deep = deep
|
39
|
+
|
40
|
+
if once is not False:
|
41
|
+
self.once = once
|
42
|
+
|
43
|
+
if flush is not None:
|
44
|
+
self.flush = flush
|
45
|
+
|
46
|
+
def _to_json_dict(self):
|
47
|
+
data = super()._to_json_dict()
|
48
|
+
|
49
|
+
if self._inputs:
|
50
|
+
data["inputs"] = self._inputs
|
51
|
+
|
52
|
+
if sum(self._is_slient_inputs) > 0:
|
53
|
+
data["slient"] = self._is_slient_inputs
|
54
|
+
|
55
|
+
if sum(self._is_data) > 0:
|
56
|
+
data["data"] = self._is_data
|
57
|
+
|
58
|
+
if self._outputs:
|
59
|
+
data["outputs"] = self._outputs
|
60
|
+
|
61
|
+
return data
|
62
|
+
|
63
|
+
|
64
|
+
def js_watch(
|
65
|
+
*,
|
66
|
+
inputs: typing.Optional[typing.Sequence] = None,
|
67
|
+
outputs: typing.Optional[typing.Sequence] = None,
|
68
|
+
code: str = "",
|
69
|
+
immediate: bool = True,
|
70
|
+
deep: typing.Union[bool, int] = False,
|
71
|
+
once: bool = False,
|
72
|
+
flush: typing.Optional[_types.TFlush] = None,
|
73
|
+
):
|
74
|
+
return JsWatch(code, inputs, outputs, immediate, deep, once, flush)
|
@@ -0,0 +1,61 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
from typing import (
|
3
|
+
Any,
|
4
|
+
Dict,
|
5
|
+
Optional,
|
6
|
+
Sequence,
|
7
|
+
Union,
|
8
|
+
cast,
|
9
|
+
)
|
10
|
+
|
11
|
+
from instaui.vars.mixin_types.observable import ObservableMixin
|
12
|
+
|
13
|
+
from . import _types
|
14
|
+
from . import _utils
|
15
|
+
|
16
|
+
from instaui.common.jsonable import Jsonable
|
17
|
+
from instaui.runtime._app import get_current_scope
|
18
|
+
|
19
|
+
|
20
|
+
class VueWatch(Jsonable):
|
21
|
+
def __init__(
|
22
|
+
self,
|
23
|
+
sources: Union[Any, Sequence],
|
24
|
+
callback: str,
|
25
|
+
*,
|
26
|
+
bindings: Optional[Dict[str, Any]] = None,
|
27
|
+
immediate: bool = False,
|
28
|
+
deep: Union[bool, int] = False,
|
29
|
+
once: bool = False,
|
30
|
+
flush: Optional[_types.TFlush] = None,
|
31
|
+
) -> None:
|
32
|
+
get_current_scope().register_vue_watch(self)
|
33
|
+
|
34
|
+
self.code = callback
|
35
|
+
|
36
|
+
if isinstance(sources, Sequence):
|
37
|
+
self.on = [
|
38
|
+
cast(ObservableMixin, varObj)._to_observable_config()
|
39
|
+
for varObj in sources
|
40
|
+
]
|
41
|
+
else:
|
42
|
+
self.on = cast(ObservableMixin, sources)._to_observable_config()
|
43
|
+
|
44
|
+
if bindings:
|
45
|
+
self.bind = {
|
46
|
+
k: cast(ObservableMixin, v)._to_observable_config()
|
47
|
+
for k, v in bindings.items()
|
48
|
+
}
|
49
|
+
|
50
|
+
if immediate is not False:
|
51
|
+
self.immediate = immediate
|
52
|
+
|
53
|
+
if deep is not False:
|
54
|
+
_utils.assert_deep(deep)
|
55
|
+
self.deep = deep
|
56
|
+
|
57
|
+
if once is not False:
|
58
|
+
self.once = once
|
59
|
+
|
60
|
+
if flush is not None:
|
61
|
+
self.flush = flush
|
@@ -0,0 +1,123 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
import inspect
|
3
|
+
import typing
|
4
|
+
from typing_extensions import ParamSpec
|
5
|
+
from . import _types
|
6
|
+
from . import _utils
|
7
|
+
|
8
|
+
from instaui.common.jsonable import Jsonable
|
9
|
+
from instaui.runtime._app import get_app_slot, get_current_scope
|
10
|
+
from instaui.handlers import watch_handler
|
11
|
+
|
12
|
+
from instaui.vars.mixin_types.py_binding import CanOutputMixin
|
13
|
+
from instaui.vars.mixin_types.common_type import TObservableInput
|
14
|
+
from instaui._helper import observable_helper
|
15
|
+
|
16
|
+
P = ParamSpec("P")
|
17
|
+
R = typing.TypeVar("R")
|
18
|
+
|
19
|
+
|
20
|
+
class WebWatch(Jsonable, typing.Generic[P, R]):
|
21
|
+
def __init__(
|
22
|
+
self,
|
23
|
+
func: typing.Callable[P, R],
|
24
|
+
inputs: typing.Optional[typing.Sequence[TObservableInput]] = None,
|
25
|
+
outputs: typing.Optional[typing.Sequence[CanOutputMixin]] = None,
|
26
|
+
immediate: bool = True,
|
27
|
+
deep: typing.Union[bool, int] = True,
|
28
|
+
once: bool = False,
|
29
|
+
flush: typing.Optional[_types.TFlush] = None,
|
30
|
+
_debug: typing.Optional[typing.Any] = None,
|
31
|
+
) -> None:
|
32
|
+
get_current_scope().register_web_watch(self)
|
33
|
+
|
34
|
+
self._inputs, self._is_slient_inputs, self._is_data = (
|
35
|
+
observable_helper.analyze_observable_inputs(list(inputs or []))
|
36
|
+
)
|
37
|
+
|
38
|
+
self._outputs = [output._to_output_config() for output in outputs or []]
|
39
|
+
self._fn = func
|
40
|
+
self._immediate = immediate
|
41
|
+
self._deep = deep
|
42
|
+
self._once = once
|
43
|
+
self._flush = flush
|
44
|
+
self._debug = _debug
|
45
|
+
|
46
|
+
def __call__(self, *args: P.args, **kwargs: P.kwargs) -> R:
|
47
|
+
return self._fn(*args, **kwargs)
|
48
|
+
|
49
|
+
def _to_json_dict(self):
|
50
|
+
data = super()._to_json_dict()
|
51
|
+
|
52
|
+
app = get_app_slot()
|
53
|
+
|
54
|
+
if app.mode == "web":
|
55
|
+
hkey = watch_handler.create_handler_key(
|
56
|
+
page_path=app.page_path,
|
57
|
+
handler=self._fn,
|
58
|
+
)
|
59
|
+
|
60
|
+
watch_handler.register_handler(hkey, self._fn, len(self._outputs))
|
61
|
+
|
62
|
+
url = (
|
63
|
+
watch_handler.ASYNC_URL
|
64
|
+
if inspect.iscoroutinefunction(self._fn)
|
65
|
+
else watch_handler.SYNC_URL
|
66
|
+
)
|
67
|
+
|
68
|
+
data["url"] = url
|
69
|
+
data["key"] = hkey
|
70
|
+
if self._inputs:
|
71
|
+
data["inputs"] = self._inputs
|
72
|
+
|
73
|
+
if sum(self._is_slient_inputs) > 0:
|
74
|
+
data["slient"] = self._is_slient_inputs
|
75
|
+
|
76
|
+
if sum(self._is_data) > 0:
|
77
|
+
data["data"] = self._is_data
|
78
|
+
|
79
|
+
if self._debug:
|
80
|
+
data["debug"] = self._debug
|
81
|
+
|
82
|
+
if self._outputs:
|
83
|
+
data["outputs"] = self._outputs
|
84
|
+
|
85
|
+
if self._immediate is not True:
|
86
|
+
data["immediate"] = self._immediate
|
87
|
+
|
88
|
+
if self._deep is not True:
|
89
|
+
_utils.assert_deep(self._deep)
|
90
|
+
data["deep"] = self._deep
|
91
|
+
if self._once is not False:
|
92
|
+
data["once"] = self._once
|
93
|
+
if self._flush is not None:
|
94
|
+
data["flush"] = self._flush
|
95
|
+
|
96
|
+
return data
|
97
|
+
|
98
|
+
return {}
|
99
|
+
|
100
|
+
|
101
|
+
def watch(
|
102
|
+
*,
|
103
|
+
inputs: typing.Optional[typing.Sequence] = None,
|
104
|
+
outputs: typing.Optional[typing.Sequence] = None,
|
105
|
+
immediate: bool = True,
|
106
|
+
deep: typing.Union[bool, int] = True,
|
107
|
+
once: bool = False,
|
108
|
+
flush: typing.Optional[_types.TFlush] = None,
|
109
|
+
_debug: typing.Optional[typing.Any] = None,
|
110
|
+
):
|
111
|
+
def wrapper(func: typing.Callable[P, R]):
|
112
|
+
return WebWatch(
|
113
|
+
func,
|
114
|
+
inputs,
|
115
|
+
outputs=outputs,
|
116
|
+
immediate=immediate,
|
117
|
+
deep=deep,
|
118
|
+
once=once,
|
119
|
+
flush=flush,
|
120
|
+
_debug=_debug,
|
121
|
+
)
|
122
|
+
|
123
|
+
return wrapper
|
instaui/zero/__init__.py
ADDED
instaui/zero/scope.py
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2024 CrystalWindSnake
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
@@ -0,0 +1,154 @@
|
|
1
|
+
Metadata-Version: 2.3
|
2
|
+
Name: instaui
|
3
|
+
Version: 0.1.0
|
4
|
+
Summary: insta-ui is a Python-based UI library for rapidly building user interfaces.
|
5
|
+
License: MIT
|
6
|
+
Author: CrystalWindSnake
|
7
|
+
Author-email: 568166495@qq.com
|
8
|
+
Requires-Python: >=3.8,<3.13
|
9
|
+
Classifier: License :: OSI Approved :: MIT License
|
10
|
+
Classifier: Programming Language :: Python :: 3
|
11
|
+
Classifier: Programming Language :: Python :: 3.8
|
12
|
+
Classifier: Programming Language :: Python :: 3.9
|
13
|
+
Classifier: Programming Language :: Python :: 3.10
|
14
|
+
Classifier: Programming Language :: Python :: 3.11
|
15
|
+
Classifier: Programming Language :: Python :: 3.12
|
16
|
+
Provides-Extra: web
|
17
|
+
Provides-Extra: webview
|
18
|
+
Requires-Dist: fastapi ; extra == "web"
|
19
|
+
Requires-Dist: jinja2 (>=3.1.4,<4.0.0)
|
20
|
+
Requires-Dist: orjson (>=3.10.15,<4.0.0)
|
21
|
+
Requires-Dist: pydantic (>=2.10.6,<3.0.0)
|
22
|
+
Requires-Dist: pywebview ; extra == "webview"
|
23
|
+
Requires-Dist: typing-extensions (>=4.12.2,<5.0.0)
|
24
|
+
Requires-Dist: uvicorn ; extra == "web"
|
25
|
+
Description-Content-Type: text/markdown
|
26
|
+
|
27
|
+
# insta-ui
|
28
|
+
|
29
|
+
<div align="center">
|
30
|
+
|
31
|
+
English| [简体中文](./README.md)
|
32
|
+
|
33
|
+
</div>
|
34
|
+
|
35
|
+
|
36
|
+
## 📖 Introduction
|
37
|
+
insta-ui is a Python-based UI library for rapidly building user interfaces.
|
38
|
+
|
39
|
+
|
40
|
+
## ⚙️ Features
|
41
|
+
|
42
|
+
Three modes are provided:
|
43
|
+
|
44
|
+
- Zero mode: Generates pure HTML files, requiring no dependencies. Simply open in a browser to run.
|
45
|
+
- Web mode: Generates web applications.
|
46
|
+
- Web view mode: Generates web view applications that can be packaged into local applications (without needing to start a web server).
|
47
|
+
|
48
|
+
|
49
|
+
## 📦 Installation
|
50
|
+
|
51
|
+
For zero mode:
|
52
|
+
|
53
|
+
```
|
54
|
+
pip install instaui -U
|
55
|
+
```
|
56
|
+
|
57
|
+
For web mode:
|
58
|
+
|
59
|
+
```
|
60
|
+
pip install instaui[web] -U
|
61
|
+
```
|
62
|
+
|
63
|
+
For web view mode:
|
64
|
+
```
|
65
|
+
pip install instaui[webview] -U
|
66
|
+
```
|
67
|
+
|
68
|
+
|
69
|
+
|
70
|
+
## 🖥️ Quick Start
|
71
|
+
|
72
|
+
Here's a Counter example where clicking the button will display the current count value on the button text.
|
73
|
+
|
74
|
+
zore mode:
|
75
|
+
|
76
|
+
```python
|
77
|
+
from instaui import ui, html, zero
|
78
|
+
|
79
|
+
with zero():
|
80
|
+
count = ui.ref(0)
|
81
|
+
text = ui.str_format("Count: {}", count)
|
82
|
+
|
83
|
+
html.button(text).on_click(
|
84
|
+
"()=> count.value++", bindings={"count": count}
|
85
|
+
)
|
86
|
+
|
87
|
+
ui.to_html("./test.html")
|
88
|
+
|
89
|
+
```
|
90
|
+
|
91
|
+
Running the above code will generate a test.html file, which you can open in a browser to see the effect.
|
92
|
+
|
93
|
+
|
94
|
+
|
95
|
+
Web mode:
|
96
|
+
|
97
|
+
```python
|
98
|
+
from instaui import ui, html
|
99
|
+
|
100
|
+
@ui.page("/")
|
101
|
+
def counter():
|
102
|
+
count = ui.ref(0)
|
103
|
+
text = ui.str_format("Count: {}", count)
|
104
|
+
|
105
|
+
html.button(text).on_click("()=> count.value++", bindings={"count": count})
|
106
|
+
|
107
|
+
|
108
|
+
ui.server().run()
|
109
|
+
```
|
110
|
+
|
111
|
+
In web mode, we can define interaction functions for complex computations.
|
112
|
+
|
113
|
+
```python
|
114
|
+
from instaui import ui, html
|
115
|
+
|
116
|
+
@ui.page("/")
|
117
|
+
def counter():
|
118
|
+
count = ui.ref(0)
|
119
|
+
# text = ui.str_format("Count: {}", count)
|
120
|
+
|
121
|
+
@ui.computed(inputs=[count])
|
122
|
+
def text(count: int):
|
123
|
+
# Any Python operation
|
124
|
+
return f"Current Count: {count}"
|
125
|
+
|
126
|
+
|
127
|
+
html.button(text).on_click("()=> count.value++", bindings={"count": count})
|
128
|
+
|
129
|
+
|
130
|
+
ui.server().run()
|
131
|
+
```
|
132
|
+
|
133
|
+
- The computation of `text` will generate network requests.
|
134
|
+
- Button clicks, due to using JS binding, do not require network requests.
|
135
|
+
|
136
|
+
You can choose to handle any computation with either Python or JavaScript. Below is an example of handling the button click event using Python.
|
137
|
+
|
138
|
+
```python
|
139
|
+
@ui.page("/")
|
140
|
+
def counter():
|
141
|
+
count = ui.ref(0)
|
142
|
+
|
143
|
+
@ui.computed(inputs=[count])
|
144
|
+
def text(count: int):
|
145
|
+
return f"Current Count: {count}"
|
146
|
+
|
147
|
+
@ui.event(inputs=[count], outputs=[count])
|
148
|
+
def add_count(count: int):
|
149
|
+
return count + 1
|
150
|
+
|
151
|
+
html.button(text).on_click(add_count)
|
152
|
+
|
153
|
+
```
|
154
|
+
|