ex4nicegui 0.6.6__py3-none-any.whl → 0.6.8__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.
- ex4nicegui/__init__.py +10 -6
- ex4nicegui/gsap/__init__.py +11 -0
- ex4nicegui/helper/__init__.py +4 -0
- ex4nicegui/helper/client_instance_locker.py +31 -0
- ex4nicegui/libs/gsap/.DS_Store +0 -0
- ex4nicegui/libs/gsap/gsap.mjs +6 -0
- ex4nicegui/reactive/EChartsComponent/ECharts.js +19 -9
- ex4nicegui/reactive/local_file_picker.py +1 -2
- ex4nicegui/reactive/officials/aggrid.py +7 -7
- ex4nicegui/reactive/officials/base.py +198 -86
- ex4nicegui/reactive/officials/button.py +5 -5
- ex4nicegui/reactive/officials/checkbox.py +5 -6
- ex4nicegui/reactive/officials/circular_progress.py +5 -6
- ex4nicegui/reactive/officials/color_picker.py +7 -8
- ex4nicegui/reactive/officials/column.py +4 -3
- ex4nicegui/reactive/officials/date.py +6 -12
- ex4nicegui/reactive/officials/drawer.py +2 -3
- ex4nicegui/reactive/officials/echarts.py +32 -15
- ex4nicegui/reactive/officials/expansion.py +5 -5
- ex4nicegui/reactive/officials/grid.py +1 -1
- ex4nicegui/reactive/officials/html.py +1 -3
- ex4nicegui/reactive/officials/icon.py +9 -10
- ex4nicegui/reactive/officials/image.py +5 -7
- ex4nicegui/reactive/officials/input.py +8 -10
- ex4nicegui/reactive/officials/knob.py +5 -7
- ex4nicegui/reactive/officials/label.py +5 -4
- ex4nicegui/reactive/officials/linear_progress.py +9 -10
- ex4nicegui/reactive/officials/number.py +23 -8
- ex4nicegui/reactive/officials/radio.py +7 -9
- ex4nicegui/reactive/officials/row.py +1 -1
- ex4nicegui/reactive/officials/select.py +7 -9
- ex4nicegui/reactive/officials/slider.py +6 -8
- ex4nicegui/reactive/officials/switch.py +5 -7
- ex4nicegui/reactive/officials/tab.py +1 -1
- ex4nicegui/reactive/officials/tab_panel.py +1 -1
- ex4nicegui/reactive/officials/tab_panels.py +15 -3
- ex4nicegui/reactive/officials/table.py +12 -10
- ex4nicegui/reactive/officials/tabs.py +4 -3
- ex4nicegui/reactive/officials/textarea.py +6 -8
- ex4nicegui/reactive/officials/upload.py +2 -2
- ex4nicegui/reactive/q_pagination.py +5 -4
- ex4nicegui/reactive/scopedStyle.js +55 -0
- ex4nicegui/reactive/scopedStyle.py +22 -0
- ex4nicegui/reactive/services/color_service.py +56 -0
- ex4nicegui/reactive/services/pandas_service.py +31 -0
- ex4nicegui/reactive/{utils.py → services/reactive_service.py} +9 -67
- ex4nicegui/reactive/systems/color_system.py +25 -0
- ex4nicegui/reactive/systems/object_system.py +33 -0
- ex4nicegui/reactive/systems/reactive_system.py +21 -0
- ex4nicegui/reactive/useMouse/UseMouse.py +4 -4
- ex4nicegui/reactive/usePagination.py +1 -1
- ex4nicegui/reactive/vfor.py +1 -2
- ex4nicegui/reactive/vmodel.py +1 -1
- ex4nicegui/utils/refComputed.py +147 -0
- ex4nicegui/utils/refWrapper.py +57 -0
- ex4nicegui/utils/signals.py +51 -192
- ex4nicegui/utils/types.py +16 -0
- ex4nicegui/version.py +3 -0
- {ex4nicegui-0.6.6.dist-info → ex4nicegui-0.6.8.dist-info}/METADATA +1274 -1124
- {ex4nicegui-0.6.6.dist-info → ex4nicegui-0.6.8.dist-info}/RECORD +81 -74
- {ex4nicegui-0.6.6.dist-info → ex4nicegui-0.6.8.dist-info}/WHEEL +1 -2
- ex4nicegui/reactive/EChartsComponent/__init__.py +0 -0
- ex4nicegui/reactive/UseDraggable/__init__.py +0 -0
- ex4nicegui/reactive/dropZone/__init__.py +0 -0
- ex4nicegui/reactive/mermaid/__init__.py +0 -0
- ex4nicegui/reactive/officials/__init__.py +0 -1
- ex4nicegui/reactive/officials/utils.py +0 -11
- ex4nicegui/reactive/useMouse/__init__.py +0 -0
- ex4nicegui-0.6.6.dist-info/top_level.txt +0 -1
- {ex4nicegui-0.6.6.dist-info → ex4nicegui-0.6.8.dist-info}/LICENSE +0 -0
|
@@ -5,36 +5,16 @@ from typing import (
|
|
|
5
5
|
Iterable,
|
|
6
6
|
List,
|
|
7
7
|
Optional,
|
|
8
|
-
Protocol,
|
|
9
8
|
Tuple,
|
|
10
9
|
cast,
|
|
11
|
-
runtime_checkable,
|
|
12
|
-
Union,
|
|
13
10
|
)
|
|
14
|
-
|
|
15
|
-
from ex4nicegui.utils.signals import is_ref,
|
|
11
|
+
from nicegui import ui
|
|
12
|
+
from ex4nicegui.utils.signals import is_ref, is_setter_ref
|
|
16
13
|
from nicegui.events import handle_event
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
pass
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
@runtime_checkable
|
|
25
|
-
class GetItemProtocol(Protocol):
|
|
26
|
-
def __getitem__(self, key):
|
|
27
|
-
...
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
@runtime_checkable
|
|
31
|
-
class SetItemProtocol(Protocol):
|
|
32
|
-
def __setitem__(self, key, value):
|
|
33
|
-
...
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
def _convert_kws_ref2value(kws: Dict) -> Dict:
|
|
37
|
-
return {key: to_value(value) for key, value in kws.items()}
|
|
14
|
+
from ex4nicegui.reactive.systems.reactive_system import (
|
|
15
|
+
convert_kws_ref2value,
|
|
16
|
+
inject_method,
|
|
17
|
+
)
|
|
38
18
|
|
|
39
19
|
|
|
40
20
|
class ParameterClassifier:
|
|
@@ -75,7 +55,7 @@ class ParameterClassifier:
|
|
|
75
55
|
)
|
|
76
56
|
|
|
77
57
|
def get_values_kws(self) -> Dict:
|
|
78
|
-
value_kws =
|
|
58
|
+
value_kws = convert_kws_ref2value(
|
|
79
59
|
{k: v for k, v in self._args.items() if k not in self.events}
|
|
80
60
|
)
|
|
81
61
|
|
|
@@ -105,43 +85,5 @@ class ParameterClassifier:
|
|
|
105
85
|
}
|
|
106
86
|
|
|
107
87
|
|
|
108
|
-
def
|
|
109
|
-
|
|
110
|
-
return obj[name]
|
|
111
|
-
return getattr(obj, name) # type: ignore
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
def set_attribute(
|
|
115
|
-
obj: Union[object, SetItemProtocol], name: Union[str, int], value: Any
|
|
116
|
-
) -> None:
|
|
117
|
-
if isinstance(obj, SetItemProtocol):
|
|
118
|
-
obj[name] = value
|
|
119
|
-
else:
|
|
120
|
-
setattr(obj, name, value) # type: ignore
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
def dataframe2col_str(df, copy=True):
|
|
124
|
-
if isinstance(df.columns, pd.MultiIndex):
|
|
125
|
-
raise ValueError(
|
|
126
|
-
"MultiIndex columns are not supported. "
|
|
127
|
-
"You can convert them to strings using something like "
|
|
128
|
-
'`df.columns = ["_".join(col) for col in df.columns.values]`.'
|
|
129
|
-
)
|
|
130
|
-
|
|
131
|
-
date_cols = df.columns[df.dtypes == "datetime64[ns]"]
|
|
132
|
-
time_cols = df.columns[df.dtypes == "timedelta64[ns]"]
|
|
133
|
-
complex_cols = df.columns[df.dtypes == "complex128"]
|
|
134
|
-
period_cols = df.columns[df.dtypes == "period[M]"]
|
|
135
|
-
if (
|
|
136
|
-
len(date_cols) != 0
|
|
137
|
-
or len(time_cols) != 0
|
|
138
|
-
or len(complex_cols) != 0
|
|
139
|
-
or len(period_cols) != 0
|
|
140
|
-
):
|
|
141
|
-
df = df.copy() if copy else df
|
|
142
|
-
df[date_cols] = df[date_cols].astype(str)
|
|
143
|
-
df[time_cols] = df[time_cols].astype(str)
|
|
144
|
-
df[complex_cols] = df[complex_cols].astype(str)
|
|
145
|
-
df[period_cols] = df[period_cols].astype(str)
|
|
146
|
-
|
|
147
|
-
return df
|
|
88
|
+
def inject_handle_delete(element: ui.element, on_delete: Callable[[], None]):
|
|
89
|
+
inject_method(element, "_handle_delete", on_delete)
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import Literal
|
|
4
|
+
|
|
5
|
+
from nicegui.elements.mixins.color_elements import (
|
|
6
|
+
QUASAR_COLORS,
|
|
7
|
+
TAILWIND_COLORS,
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
_color_system_type = Literal["QUASAR", "TAILWIND", "STYLE"]
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def get_text_color_info(name: str):
|
|
15
|
+
system_type: _color_system_type = "STYLE"
|
|
16
|
+
|
|
17
|
+
if name in QUASAR_COLORS:
|
|
18
|
+
system_type = "QUASAR"
|
|
19
|
+
elif name in TAILWIND_COLORS:
|
|
20
|
+
system_type = "TAILWIND"
|
|
21
|
+
name = f"text-{name}"
|
|
22
|
+
else:
|
|
23
|
+
pass
|
|
24
|
+
|
|
25
|
+
return system_type, name
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
from typing import (
|
|
2
|
+
Any,
|
|
3
|
+
Protocol,
|
|
4
|
+
runtime_checkable,
|
|
5
|
+
Union,
|
|
6
|
+
)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
@runtime_checkable
|
|
10
|
+
class GetItemProtocol(Protocol):
|
|
11
|
+
def __getitem__(self, key):
|
|
12
|
+
...
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@runtime_checkable
|
|
16
|
+
class SetItemProtocol(Protocol):
|
|
17
|
+
def __setitem__(self, key, value):
|
|
18
|
+
...
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def get_attribute(obj: Union[object, GetItemProtocol], name: Union[str, int]) -> Any:
|
|
22
|
+
if isinstance(obj, (GetItemProtocol)):
|
|
23
|
+
return obj[name]
|
|
24
|
+
return getattr(obj, name) # type: ignore
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def set_attribute(
|
|
28
|
+
obj: Union[object, SetItemProtocol], name: Union[str, int], value: Any
|
|
29
|
+
) -> None:
|
|
30
|
+
if isinstance(obj, SetItemProtocol):
|
|
31
|
+
obj[name] = value
|
|
32
|
+
else:
|
|
33
|
+
setattr(obj, name, value) # type: ignore
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
from typing import Callable, Dict
|
|
2
|
+
from ex4nicegui.utils.signals import to_value
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def convert_kws_ref2value(kws: Dict) -> Dict:
|
|
6
|
+
return {key: to_value(value) for key, value in kws.items()}
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def inject_method(obj, method_name: str, new_handle: Callable):
|
|
10
|
+
if hasattr(obj, method_name):
|
|
11
|
+
original_method = getattr(obj, method_name)
|
|
12
|
+
|
|
13
|
+
def injected_method(*args, **kwargs):
|
|
14
|
+
new_handle(*args, **kwargs)
|
|
15
|
+
return original_method(*args, **kwargs)
|
|
16
|
+
|
|
17
|
+
setattr(obj, method_name, injected_method)
|
|
18
|
+
else:
|
|
19
|
+
raise AttributeError(
|
|
20
|
+
f"'{type(obj).__name__}' object has no attribute '{method_name}'."
|
|
21
|
+
)
|
|
@@ -4,7 +4,7 @@ from nicegui.dataclasses import KWONLY_SLOTS
|
|
|
4
4
|
from nicegui.events import handle_event, UiEventArguments
|
|
5
5
|
from nicegui.element import Element
|
|
6
6
|
|
|
7
|
-
from ex4nicegui.utils.signals import
|
|
7
|
+
from ex4nicegui.utils.signals import TReadonlyRef, batch, to_ref
|
|
8
8
|
|
|
9
9
|
_Update_Args = [
|
|
10
10
|
"x",
|
|
@@ -42,15 +42,15 @@ class UseMouse(Element, component="UseMouse.js"):
|
|
|
42
42
|
|
|
43
43
|
@property
|
|
44
44
|
def x(self):
|
|
45
|
-
return cast(
|
|
45
|
+
return cast(TReadonlyRef[float], self.__x)
|
|
46
46
|
|
|
47
47
|
@property
|
|
48
48
|
def y(self):
|
|
49
|
-
return cast(
|
|
49
|
+
return cast(TReadonlyRef[float], self.__y)
|
|
50
50
|
|
|
51
51
|
@property
|
|
52
52
|
def sourceType(self):
|
|
53
|
-
return cast(
|
|
53
|
+
return cast(TReadonlyRef[float], self.__sourceType)
|
|
54
54
|
|
|
55
55
|
def on_update(self, handler: Optional[Callable[..., Any]]):
|
|
56
56
|
def inner_handler(e):
|
ex4nicegui/reactive/vfor.py
CHANGED
|
@@ -26,9 +26,8 @@ from typing import (
|
|
|
26
26
|
from functools import partial
|
|
27
27
|
from dataclasses import dataclass
|
|
28
28
|
from signe.core.scope import Scope
|
|
29
|
-
from .
|
|
29
|
+
from ex4nicegui.reactive.systems.object_system import get_attribute
|
|
30
30
|
from ex4nicegui.reactive.empty import Empty
|
|
31
|
-
# from .transitionGroup import TransitionGroup
|
|
32
31
|
|
|
33
32
|
_T = TypeVar("_T")
|
|
34
33
|
_T_data = Union[List[Any], TGetterOrReadonlyRef[List[Any]], RefWrapper]
|
ex4nicegui/reactive/vmodel.py
CHANGED
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
from functools import partial
|
|
2
|
+
import types
|
|
3
|
+
import signe
|
|
4
|
+
from .clientScope import _CLIENT_SCOPE_MANAGER
|
|
5
|
+
from typing import (
|
|
6
|
+
Any,
|
|
7
|
+
Dict,
|
|
8
|
+
Protocol,
|
|
9
|
+
Type,
|
|
10
|
+
TypeVar,
|
|
11
|
+
Generic,
|
|
12
|
+
overload,
|
|
13
|
+
Optional,
|
|
14
|
+
Callable,
|
|
15
|
+
cast,
|
|
16
|
+
Union,
|
|
17
|
+
)
|
|
18
|
+
from .scheduler import get_uiScheduler
|
|
19
|
+
from .types import (
|
|
20
|
+
ReadonlyRef,
|
|
21
|
+
DescReadonlyRef,
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
T = TypeVar("T", covariant=True)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class TInstanceCall(Protocol[T]):
|
|
29
|
+
def __call__(_, self) -> T: # type: ignore
|
|
30
|
+
...
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
@overload
|
|
34
|
+
def ref_computed(
|
|
35
|
+
fn: Union[Callable[[], T], TInstanceCall[T]],
|
|
36
|
+
*,
|
|
37
|
+
desc="",
|
|
38
|
+
debug_trigger: Optional[Callable[..., None]] = None,
|
|
39
|
+
priority_level: int = 1,
|
|
40
|
+
debug_name: Optional[str] = None,
|
|
41
|
+
) -> ReadonlyRef[T]:
|
|
42
|
+
"""Takes a getter function and returns a readonly reactive ref object for the returned value from the getter. It can also take an object with get and set functions to create a writable ref object.
|
|
43
|
+
|
|
44
|
+
@see - https://github.com/CrystalWindSnake/ex4nicegui/blob/main/README.en.md#ref_computed
|
|
45
|
+
@中文文档 - https://gitee.com/carson_add/ex4nicegui/tree/main/#ref_computed
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
Args:
|
|
49
|
+
fn (Callable[[], T]): _description_
|
|
50
|
+
desc (str, optional): _description_. Defaults to "".
|
|
51
|
+
debug_trigger (Optional[Callable[..., None]], optional): _description_. Defaults to None.
|
|
52
|
+
priority_level (int, optional): _description_. Defaults to 1.
|
|
53
|
+
debug_name (Optional[str], optional): _description_. Defaults to None.
|
|
54
|
+
|
|
55
|
+
"""
|
|
56
|
+
...
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
@overload
|
|
60
|
+
def ref_computed(
|
|
61
|
+
fn=None,
|
|
62
|
+
*,
|
|
63
|
+
desc="",
|
|
64
|
+
debug_trigger: Optional[Callable[..., None]] = None,
|
|
65
|
+
priority_level: int = 1,
|
|
66
|
+
debug_name: Optional[str] = None,
|
|
67
|
+
) -> Callable[[Callable[..., T]], ReadonlyRef[T]]:
|
|
68
|
+
...
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def ref_computed(
|
|
72
|
+
fn: Optional[Union[Callable[[], T], TInstanceCall[T]]] = None,
|
|
73
|
+
*,
|
|
74
|
+
desc="",
|
|
75
|
+
debug_trigger: Optional[Callable[..., None]] = None,
|
|
76
|
+
priority_level: int = 1,
|
|
77
|
+
debug_name: Optional[str] = None,
|
|
78
|
+
) -> Union[ReadonlyRef[T], Callable[[Callable[..., T]], ReadonlyRef[T]]]:
|
|
79
|
+
kws = {
|
|
80
|
+
"debug_trigger": debug_trigger,
|
|
81
|
+
"priority_level": priority_level,
|
|
82
|
+
"debug_name": debug_name,
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
if fn:
|
|
86
|
+
if _helpers.is_class_define_method(fn):
|
|
87
|
+
return cast(
|
|
88
|
+
ref_computed_method[T],
|
|
89
|
+
ref_computed_method(fn, computed_args=kws), # type: ignore
|
|
90
|
+
) # type: ignore
|
|
91
|
+
|
|
92
|
+
getter = signe.Computed(
|
|
93
|
+
cast(Callable[[], T], fn),
|
|
94
|
+
**kws,
|
|
95
|
+
scope=_CLIENT_SCOPE_MANAGER.get_current_scope(),
|
|
96
|
+
scheduler=get_uiScheduler(),
|
|
97
|
+
)
|
|
98
|
+
return cast(DescReadonlyRef[T], getter)
|
|
99
|
+
|
|
100
|
+
else:
|
|
101
|
+
|
|
102
|
+
def wrap(fn: Callable[[], T]):
|
|
103
|
+
return ref_computed(fn, **kws)
|
|
104
|
+
|
|
105
|
+
return wrap
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
class ref_computed_method(Generic[T]):
|
|
109
|
+
__isabstractmethod__: bool
|
|
110
|
+
|
|
111
|
+
def __init__(self, fget: Callable[[Any], T], computed_args: Dict) -> None:
|
|
112
|
+
self._fget = fget
|
|
113
|
+
self._computed_args = computed_args
|
|
114
|
+
|
|
115
|
+
def __set_name__(self, owner, name):
|
|
116
|
+
_helpers.add_computed_to_instance(owner, name, self._fget, self._computed_args)
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
class _helpers:
|
|
120
|
+
@staticmethod
|
|
121
|
+
def is_class_define_method(fn: Callable):
|
|
122
|
+
has_name = hasattr(fn, "__name__")
|
|
123
|
+
qualname_prefix = f".<locals>.{fn.__name__}" if has_name else ""
|
|
124
|
+
|
|
125
|
+
return (
|
|
126
|
+
hasattr(fn, "__qualname__")
|
|
127
|
+
and has_name
|
|
128
|
+
and "." in fn.__qualname__
|
|
129
|
+
and qualname_prefix != fn.__qualname__[-len(qualname_prefix) :]
|
|
130
|
+
and (isinstance(fn, types.FunctionType))
|
|
131
|
+
)
|
|
132
|
+
|
|
133
|
+
@staticmethod
|
|
134
|
+
def add_computed_to_instance(
|
|
135
|
+
cls_type: Type, attr_name: str, fn: Callable, computed_args: Dict
|
|
136
|
+
):
|
|
137
|
+
"""
|
|
138
|
+
Add an attribute to an instance of a class.
|
|
139
|
+
"""
|
|
140
|
+
original_init = cls_type.__init__
|
|
141
|
+
|
|
142
|
+
def new_init(self, *args, **kwargs):
|
|
143
|
+
original_init(self, *args, **kwargs)
|
|
144
|
+
setattr(self, attr_name, ref_computed(partial(fn, self), **computed_args))
|
|
145
|
+
|
|
146
|
+
cls_type.__init__ = new_init
|
|
147
|
+
return cls_type
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import signe
|
|
2
|
+
from typing import (
|
|
3
|
+
TypeVar,
|
|
4
|
+
Generic,
|
|
5
|
+
Optional,
|
|
6
|
+
Callable,
|
|
7
|
+
cast,
|
|
8
|
+
)
|
|
9
|
+
import warnings
|
|
10
|
+
from .types import (
|
|
11
|
+
TGetterOrReadonlyRef,
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
T = TypeVar("T")
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class RefWrapper(Generic[T]):
|
|
18
|
+
__slot__ = ("_getter_fn", "_setter_fn", "")
|
|
19
|
+
|
|
20
|
+
def __init__(
|
|
21
|
+
self,
|
|
22
|
+
getter_or_ref: TGetterOrReadonlyRef[T],
|
|
23
|
+
setter_or_ref: Optional[Callable[[T], None]] = None,
|
|
24
|
+
):
|
|
25
|
+
if signe.is_signal(getter_or_ref):
|
|
26
|
+
self._getter_fn = lambda: getter_or_ref.value
|
|
27
|
+
|
|
28
|
+
def ref_setter(v):
|
|
29
|
+
getter_or_ref.value = v # type: ignore
|
|
30
|
+
|
|
31
|
+
self._setter_fn = ref_setter
|
|
32
|
+
elif isinstance(getter_or_ref, Callable):
|
|
33
|
+
self._getter_fn = getter_or_ref
|
|
34
|
+
self._setter_fn = setter_or_ref or (lambda x: None)
|
|
35
|
+
else:
|
|
36
|
+
self._getter_fn = lambda: getter_or_ref
|
|
37
|
+
self._setter_fn = lambda x: None
|
|
38
|
+
|
|
39
|
+
self._is_readonly = False
|
|
40
|
+
|
|
41
|
+
@property
|
|
42
|
+
def value(self) -> T:
|
|
43
|
+
return cast(T, self._getter_fn())
|
|
44
|
+
|
|
45
|
+
@value.setter
|
|
46
|
+
def value(self, new_value: T):
|
|
47
|
+
if self._is_readonly:
|
|
48
|
+
warnings.warn("readonly ref cannot be assigned.")
|
|
49
|
+
return
|
|
50
|
+
return self._setter_fn(new_value)
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def to_ref_wrapper(
|
|
54
|
+
getter_or_ref: TGetterOrReadonlyRef[T],
|
|
55
|
+
setter_or_ref: Optional[Callable[[T], None]] = None,
|
|
56
|
+
):
|
|
57
|
+
return RefWrapper(getter_or_ref, setter_or_ref)
|