solara-ui 1.51.0__py3-none-any.whl → 1.52.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.
- solara/__init__.py +1 -1
- solara/__main__.py +3 -3
- solara/components/component_vue.py +69 -9
- solara/server/patch.py +1 -1
- solara/server/static/solara_bootstrap.py +1 -1
- {solara_ui-1.51.0.dist-info → solara_ui-1.52.0.dist-info}/METADATA +1 -1
- {solara_ui-1.51.0.dist-info → solara_ui-1.52.0.dist-info}/RECORD +11 -11
- {solara_ui-1.51.0.data → solara_ui-1.52.0.data}/data/etc/jupyter/jupyter_notebook_config.d/solara.json +0 -0
- {solara_ui-1.51.0.data → solara_ui-1.52.0.data}/data/etc/jupyter/jupyter_server_config.d/solara.json +0 -0
- {solara_ui-1.51.0.dist-info → solara_ui-1.52.0.dist-info}/WHEEL +0 -0
- {solara_ui-1.51.0.dist-info → solara_ui-1.52.0.dist-info}/licenses/LICENSE +0 -0
solara/__init__.py
CHANGED
solara/__main__.py
CHANGED
|
@@ -13,7 +13,7 @@ import rich
|
|
|
13
13
|
import rich_click as click
|
|
14
14
|
import uvicorn
|
|
15
15
|
from rich import print as rprint
|
|
16
|
-
from uvicorn.main import LEVEL_CHOICES
|
|
16
|
+
from uvicorn.main import LEVEL_CHOICES
|
|
17
17
|
|
|
18
18
|
import solara
|
|
19
19
|
from solara.server import settings
|
|
@@ -242,9 +242,9 @@ if "SOLARA_MODE" in os.environ:
|
|
|
242
242
|
@click.argument("app")
|
|
243
243
|
@click.option(
|
|
244
244
|
"--loop",
|
|
245
|
-
type=
|
|
245
|
+
type=str,
|
|
246
246
|
default="auto",
|
|
247
|
-
help="Event loop implementation.",
|
|
247
|
+
help="Event loop implementation (see uvicorn documentation for possible values).",
|
|
248
248
|
show_default=True,
|
|
249
249
|
)
|
|
250
250
|
@click.option(
|
|
@@ -12,17 +12,32 @@ import solara
|
|
|
12
12
|
|
|
13
13
|
P = typing_extensions.ParamSpec("P")
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
default_to_json = widgets.widget_serialization["to_json"]
|
|
16
|
+
default_from_json = widgets.widget_serialization["from_json"]
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def _widget_from_signature(
|
|
20
|
+
classname,
|
|
21
|
+
base_class: Type[widgets.Widget],
|
|
22
|
+
func: Callable[..., None],
|
|
23
|
+
event_prefix: str,
|
|
24
|
+
tags: Dict[str, Any],
|
|
25
|
+
to_json: Dict[str, Callable[[Any, widgets.Widget], Any]],
|
|
26
|
+
from_json: Dict[str, Callable[[Any, widgets.Widget], Any]],
|
|
27
|
+
) -> Type[widgets.Widget]:
|
|
17
28
|
classprops: Dict[str, Any] = {}
|
|
18
29
|
|
|
19
30
|
parameters = inspect.signature(func).parameters
|
|
20
31
|
for name, param in parameters.items():
|
|
21
32
|
if name.startswith("event_"):
|
|
22
33
|
event_name = name[6:]
|
|
34
|
+
event_name_full = name # LLM's are quick stubborn in wanting to call `event_foo` instead of `foo`
|
|
23
35
|
|
|
24
36
|
def event_handler(self, data, buffers=None, event_name=event_name, param=param):
|
|
25
37
|
callback = self._event_callbacks.get(event_name, param.default)
|
|
38
|
+
if not callback:
|
|
39
|
+
# support 'event_foo'
|
|
40
|
+
callback = self._event_callbacks.get(event_name_full, None)
|
|
26
41
|
if callback:
|
|
27
42
|
if buffers:
|
|
28
43
|
callback(data, buffers)
|
|
@@ -30,6 +45,7 @@ def _widget_from_signature(classname, base_class: Type[widgets.Widget], func: Ca
|
|
|
30
45
|
callback(data)
|
|
31
46
|
|
|
32
47
|
classprops[f"vue_{event_name}"] = event_handler
|
|
48
|
+
classprops[f"vue_{event_name_full}"] = event_handler
|
|
33
49
|
elif name.startswith("on_") and name[3:] in parameters:
|
|
34
50
|
# callback, will be handled by reacton
|
|
35
51
|
continue
|
|
@@ -38,7 +54,9 @@ def _widget_from_signature(classname, base_class: Type[widgets.Widget], func: Ca
|
|
|
38
54
|
trait = traitlets.Any()
|
|
39
55
|
else:
|
|
40
56
|
trait = traitlets.Any(default_value=param.default)
|
|
41
|
-
|
|
57
|
+
tag = dict(sync=True, to_json=to_json.get(name, default_to_json), from_json=from_json.get(name, default_from_json))
|
|
58
|
+
tag.update(**tags.get(name, {}))
|
|
59
|
+
classprops[name] = trait.tag(**tag)
|
|
42
60
|
# maps event_foo to a callable
|
|
43
61
|
classprops["_event_callbacks"] = traitlets.Dict(default_value={})
|
|
44
62
|
|
|
@@ -46,7 +64,13 @@ def _widget_from_signature(classname, base_class: Type[widgets.Widget], func: Ca
|
|
|
46
64
|
return widget_class
|
|
47
65
|
|
|
48
66
|
|
|
49
|
-
def _widget_vue(
|
|
67
|
+
def _widget_vue(
|
|
68
|
+
vue_path: str,
|
|
69
|
+
vuetify=True,
|
|
70
|
+
to_json: Dict[str, Callable[[Any, widgets.Widget], Any]] = {},
|
|
71
|
+
from_json: Dict[str, Callable[[Any, widgets.Widget], Any]] = {},
|
|
72
|
+
tags: Dict[str, Any] = {},
|
|
73
|
+
) -> Callable[[Callable[P, None]], Type[v.VuetifyTemplate]]:
|
|
50
74
|
def decorator(func: Callable[P, None]):
|
|
51
75
|
class VuetifyWidgetSolara(v.VuetifyTemplate):
|
|
52
76
|
template_file = (os.path.abspath(inspect.getfile(func)), vue_path)
|
|
@@ -55,14 +79,20 @@ def _widget_vue(vue_path: str, vuetify=True) -> Callable[[Callable[P, None]], Ty
|
|
|
55
79
|
template_file = (os.path.abspath(inspect.getfile(func)), vue_path)
|
|
56
80
|
|
|
57
81
|
base_class = VuetifyWidgetSolara if vuetify else VueWidgetSolara
|
|
58
|
-
widget_class = _widget_from_signature("VueWidgetSolaraSub", base_class, func, "vue_")
|
|
82
|
+
widget_class = _widget_from_signature("VueWidgetSolaraSub", base_class, func, "vue_", to_json=to_json, from_json=from_json, tags=tags)
|
|
59
83
|
|
|
60
84
|
return widget_class
|
|
61
85
|
|
|
62
86
|
return decorator
|
|
63
87
|
|
|
64
88
|
|
|
65
|
-
def component_vue(
|
|
89
|
+
def component_vue(
|
|
90
|
+
vue_path: str,
|
|
91
|
+
vuetify=True,
|
|
92
|
+
tags: Dict[str, Any] = {},
|
|
93
|
+
to_json: Dict[str, Callable[[Any, widgets.Widget], Any]] = {},
|
|
94
|
+
from_json: Dict[str, Callable[[Any, widgets.Widget], Any]] = {},
|
|
95
|
+
) -> Callable[[Callable[P, None]], Callable[P, solara.Element]]:
|
|
66
96
|
"""Decorator to create a component backed by a Vue template.
|
|
67
97
|
|
|
68
98
|
Although many components can be made from the Python side, sometimes it is easier to write components using Vue directly.
|
|
@@ -74,14 +104,22 @@ def component_vue(vue_path: str, vuetify=True) -> Callable[[Callable[P, None]],
|
|
|
74
104
|
are assumed by refer to the same vue property, with `on_foo` being the event handler when `foo` changes from
|
|
75
105
|
the vue template.
|
|
76
106
|
|
|
77
|
-
Arguments
|
|
78
|
-
available as the function `foo` in the vue template.
|
|
107
|
+
Arguments of the form `event_foo` should be callbacks that can be called from the vue template. They are
|
|
108
|
+
available as the function `foo` and `event_foo` in the vue template.
|
|
109
|
+
|
|
110
|
+
Note that `foo` was kept for backwards compatibility, but LLM's have a tendency to use `event_foo`, so this was
|
|
111
|
+
changed to `event_foo`.
|
|
79
112
|
|
|
80
113
|
[See the vue v2 api](https://v2.vuejs.org/v2/api/) for more information on how to use Vue, like `watch`,
|
|
81
114
|
`methods` and lifecycle hooks such as `mounted` and `destroyed`.
|
|
82
115
|
|
|
83
116
|
See the [Vue component example](/documentation/examples/general/vue_component) for an example of how to use this decorator.
|
|
84
117
|
|
|
118
|
+
The underlying trait can be passed extra arguments by passing a dictionary to the `tags` argument.
|
|
119
|
+
The most common case is to pass a custom serializer and deserializer for the trait, for which we added the
|
|
120
|
+
strictly typed `to_json` and `from_json` arguments.
|
|
121
|
+
Otherwise pass a dictionary to the `tags` argument, see the example below for more details.
|
|
122
|
+
|
|
85
123
|
|
|
86
124
|
## Examples
|
|
87
125
|
|
|
@@ -105,6 +143,28 @@ def component_vue(vue_path: str, vuetify=True) -> Callable[[Callable[P, None]],
|
|
|
105
143
|
pass
|
|
106
144
|
```
|
|
107
145
|
|
|
146
|
+
## Example with custom serializer and deserializer
|
|
147
|
+
|
|
148
|
+
```python
|
|
149
|
+
import solara
|
|
150
|
+
|
|
151
|
+
def to_json_datetime(value: datetime.date, widget: widgets.Widget) -> str:
|
|
152
|
+
return value.isoformat()
|
|
153
|
+
|
|
154
|
+
def from_json_datetime(value: str, widget: widgets.Widget) -> datetime.date:
|
|
155
|
+
return datetime.date.fromisoformat(value)
|
|
156
|
+
|
|
157
|
+
@solara.component_vue("my_date_component.vue", to_json={"month": to_json_datetime}, from_json={"month": from_json_datetime})
|
|
158
|
+
def MyDateComponent(month: datetime.date, event_date_clicked: Callable):
|
|
159
|
+
pass
|
|
160
|
+
|
|
161
|
+
# the following will be the same, except that it is less strictly typed
|
|
162
|
+
@solara.component_vue("my_date_component.vue", tags={"month": {"to_json": to_json_datetime, "from_json": from_json_datetime}})
|
|
163
|
+
def MyDateComponentSame(month: datetime.date, event_date_clicked: Callable):
|
|
164
|
+
pass
|
|
165
|
+
|
|
166
|
+
```
|
|
167
|
+
|
|
108
168
|
## Arguments
|
|
109
169
|
|
|
110
170
|
* `vue_path`: The path to the Vue template file.
|
|
@@ -113,7 +173,7 @@ def component_vue(vue_path: str, vuetify=True) -> Callable[[Callable[P, None]],
|
|
|
113
173
|
"""
|
|
114
174
|
|
|
115
175
|
def decorator(func: Callable[P, None]):
|
|
116
|
-
VueWidgetSolaraSub = _widget_vue(vue_path, vuetify=vuetify)(func)
|
|
176
|
+
VueWidgetSolaraSub = _widget_vue(vue_path, vuetify=vuetify, to_json=to_json, from_json=from_json, tags=tags)(func)
|
|
117
177
|
|
|
118
178
|
def wrapper(*args, **kwargs):
|
|
119
179
|
event_callbacks = {}
|
solara/server/patch.py
CHANGED
|
@@ -280,7 +280,7 @@ def WidgetContextAwareThread__init__(self, *args, **kwargs):
|
|
|
280
280
|
self.current_context = None
|
|
281
281
|
# if we do this for the dummy threads, we got into a recursion
|
|
282
282
|
# since threading.current_thread will call the _DummyThread constructor
|
|
283
|
-
if not ("name" in kwargs and "Dummy-" in kwargs["name"]):
|
|
283
|
+
if not ("name" in kwargs and kwargs["name"] is not None and "Dummy-" in kwargs["name"]):
|
|
284
284
|
try:
|
|
285
285
|
self.current_context = kernel_context.get_current_context()
|
|
286
286
|
except RuntimeError:
|
|
@@ -119,7 +119,7 @@ async def main():
|
|
|
119
119
|
]
|
|
120
120
|
for dep in requirements:
|
|
121
121
|
await micropip.install(dep, keep_going=True)
|
|
122
|
-
await micropip.install("/wheels/solara-1.
|
|
122
|
+
await micropip.install("/wheels/solara-1.52.0-py2.py3-none-any.whl", keep_going=True)
|
|
123
123
|
import solara
|
|
124
124
|
|
|
125
125
|
el = solara.Warning("lala")
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
prefix/etc/jupyter/jupyter_notebook_config.d/solara.json,sha256=3UhTBQi6z7F7pPjmqXxfddv79c8VGR9H7zStDLp6AwY,115
|
|
2
2
|
prefix/etc/jupyter/jupyter_server_config.d/solara.json,sha256=D9J-rYxAzyD5GOqWvuPjacGUVFHsYtTfZ4FUbRzRvIA,113
|
|
3
|
-
solara/__init__.py,sha256=
|
|
4
|
-
solara/__main__.py,sha256=
|
|
3
|
+
solara/__init__.py,sha256=jGGWxx4nmYVpvRhmbrndn2DjhoXKRW2YzMlbR4K2WqE,3647
|
|
4
|
+
solara/__main__.py,sha256=J_f3D_mgiNicU_ay_I-qn08GOViSXm04Ym0mopqh2Os,24853
|
|
5
5
|
solara/_stores.py,sha256=N2Ec-61XNFXwigBx8f5QYPx7gDXenCOBdmLPXiJB45E,12320
|
|
6
6
|
solara/alias.py,sha256=9vfLzud77NP8in3OID9b5mmIO8NyrnFjN2_aE0lSb1k,216
|
|
7
7
|
solara/autorouting.py,sha256=iQ-jP5H-kdu1uZyLEFeiHG1IsOLZLzwKVtQPyXSgGSM,23093
|
|
@@ -33,7 +33,7 @@ solara/components/checkbox.py,sha256=MLQ9Hxvtv5aKLj4XO3ILWtGc6nKOUH560A2bBt0Z030
|
|
|
33
33
|
solara/components/code_highlight_css.py,sha256=J0fZHuEu8jeEKAq_HKbzgiMR1-VwMVnKA4dAOKE0AQU,235
|
|
34
34
|
solara/components/code_highlight_css.vue,sha256=UX4jtEetV1W25Uvu8xQ-TbEaBzbp_7DlXtXDO9SdZfY,5776
|
|
35
35
|
solara/components/columns.py,sha256=zC4PVGMivHMn2jCaQoV_mmRBzaF12gRTeMqyuWANMyo,5544
|
|
36
|
-
solara/components/component_vue.py,sha256=
|
|
36
|
+
solara/components/component_vue.py,sha256=feGM37HKJoZn4j0pQSAF14VIMjNaqsAatnrLVB7RisI,7675
|
|
37
37
|
solara/components/cross_filter.py,sha256=Q5vOkerWXNCtRbSboHjXcnjoys8bHv5b7G_fH1A1lio,13663
|
|
38
38
|
solara/components/dataframe.py,sha256=F-FdIjCj_rovstOVvZd3bwypKfshq3RXAF7FT2HLDVw,21032
|
|
39
39
|
solara/components/datatable.py,sha256=CO3gutSQU8tc1AfvWVlZ5pQN3r1W-e3zXRc_dlP0AaA,8015
|
|
@@ -114,7 +114,7 @@ solara/server/flask.py,sha256=sjhtTMiAUJ7oacZeL0m3Qem6E6B2knJ0ly845Ayyjio,9645
|
|
|
114
114
|
solara/server/jupytertools.py,sha256=cYFIUjLX7n0uuEXqWVWvmV6sV7R_MNg8ZZlabQgw8vk,1320
|
|
115
115
|
solara/server/kernel.py,sha256=ZIcVI-wYhjDo1o05PBjkd-Am-5wZ8lAlf7luhz5-_L8,13449
|
|
116
116
|
solara/server/kernel_context.py,sha256=C6ZIf7NTzDaQ2Z1tpDt0zcV0ZXsis2nUTKUQJ3F9Fh4,19168
|
|
117
|
-
solara/server/patch.py,sha256
|
|
117
|
+
solara/server/patch.py,sha256=KMoO3IK5sk-BWnwPNXhmGW4MGAgxGosgtUKMFf7oNm0,19902
|
|
118
118
|
solara/server/qt.py,sha256=QdMxX2T0Ol_j3QHYwInDyT5Gy4sOhYljMPYfru5kwLg,3774
|
|
119
119
|
solara/server/reload.py,sha256=BBH7QhrV1-e9RVyNE3uz1oPj1DagC3t_XSqGPNz0nJE,9747
|
|
120
120
|
solara/server/server.py,sha256=YbOVCeho_tmYC2xcrJTzDe62H_xTpwiMuqsBWvgN_2A,17125
|
|
@@ -146,7 +146,7 @@ solara/server/static/highlight-dark.css,sha256=xO8-vta9vG4s1OfJNHXWqiLWzx_gM03jo
|
|
|
146
146
|
solara/server/static/highlight.css,sha256=k8ZdT5iwrGQ5tXTQHAXuxvZrSUq3kwCdEpy3mlFoZjs,2637
|
|
147
147
|
solara/server/static/main-vuetify.js,sha256=R3qM4xMlstMpRUdRaul78p34z_Av2ONSTXksg2V9TqQ,9503
|
|
148
148
|
solara/server/static/main.js,sha256=mcx4JNQ4Lg4pNdUIqMoZos1mZyYFS48yd_JNFFJUqIE,5679
|
|
149
|
-
solara/server/static/solara_bootstrap.py,sha256=
|
|
149
|
+
solara/server/static/solara_bootstrap.py,sha256=6YKf4K-kWml7p-4kMf-Np_0t0J5sy-iykgKjLBy4Ttc,3195
|
|
150
150
|
solara/server/static/sun.svg,sha256=jEKBAGCr7b9zNYv0VUb7lMWKjnU2dX69_Ye_DZWGXJI,6855
|
|
151
151
|
solara/server/static/webworker.js,sha256=cjAFz7-SygStHJnYlJUlJs-gE_7YQeQ-WBDcmKYyjvo,1372
|
|
152
152
|
solara/server/templates/index.html.j2,sha256=JXQo1M-STFHLBOFetgG7509cAq8xUP0VAEtYDzz35fY,31
|
|
@@ -456,9 +456,9 @@ solara/widgets/vue/gridlayout.vue,sha256=LZk-YlqM7nv_7Y5TTq2xqfH1j2SLP1QOH5eiz7G
|
|
|
456
456
|
solara/widgets/vue/html.vue,sha256=48K5rjp0AdJDeRV6F3nOHW3J0WXPeHn55r5pGClK2fU,112
|
|
457
457
|
solara/widgets/vue/navigator.vue,sha256=7fkX-4_YSnnMIPUMKMvQVVEzrmhY9BFAYvHMqZqTXpI,4790
|
|
458
458
|
solara/widgets/vue/vegalite.vue,sha256=zhocRsUCNIRQCEbD16er5sYnuHU0YThatRHnorA3P18,4596
|
|
459
|
-
solara_ui-1.
|
|
460
|
-
solara_ui-1.
|
|
461
|
-
solara_ui-1.
|
|
462
|
-
solara_ui-1.
|
|
463
|
-
solara_ui-1.
|
|
464
|
-
solara_ui-1.
|
|
459
|
+
solara_ui-1.52.0.data/data/etc/jupyter/jupyter_notebook_config.d/solara.json,sha256=3UhTBQi6z7F7pPjmqXxfddv79c8VGR9H7zStDLp6AwY,115
|
|
460
|
+
solara_ui-1.52.0.data/data/etc/jupyter/jupyter_server_config.d/solara.json,sha256=D9J-rYxAzyD5GOqWvuPjacGUVFHsYtTfZ4FUbRzRvIA,113
|
|
461
|
+
solara_ui-1.52.0.dist-info/METADATA,sha256=YF-I_zRKcTcOWk1SHMNA87shS-54AP6rne0AzXiCgto,7459
|
|
462
|
+
solara_ui-1.52.0.dist-info/WHEEL,sha256=C2FUgwZgiLbznR-k0b_5k3Ai_1aASOXDss3lzCUsUug,87
|
|
463
|
+
solara_ui-1.52.0.dist-info/licenses/LICENSE,sha256=fFJUz-CWzZ9nEc4QZKu44jMEoDr5fEW-SiqljKpD82E,1086
|
|
464
|
+
solara_ui-1.52.0.dist-info/RECORD,,
|
|
File without changes
|
{solara_ui-1.51.0.data → solara_ui-1.52.0.data}/data/etc/jupyter/jupyter_server_config.d/solara.json
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|