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 CHANGED
@@ -1,6 +1,6 @@
1
1
  """Build webapps using IPywidgets"""
2
2
 
3
- __version__ = "1.51.0"
3
+ __version__ = "1.52.0"
4
4
  github_url = "https://github.com/widgetti/solara"
5
5
  git_branch = "master"
6
6
 
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, LOOP_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=LOOP_CHOICES,
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
- def _widget_from_signature(classname, base_class: Type[widgets.Widget], func: Callable[..., None], event_prefix: str) -> Type[widgets.Widget]:
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
- classprops[name] = trait.tag(sync=True, **widgets.widget_serialization)
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(vue_path: str, vuetify=True) -> Callable[[Callable[P, None]], Type[v.VuetifyTemplate]]:
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(vue_path: str, vuetify=True) -> Callable[[Callable[P, None]], Callable[P, solara.Element]]:
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 or the form `event_foo` should be callbacks that can be called from the vue template. They are
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.51.0-py2.py3-none-any.whl", keep_going=True)
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,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: solara-ui
3
- Version: 1.51.0
3
+ Version: 1.52.0
4
4
  Dynamic: Summary
5
5
  Project-URL: Home, https://www.github.com/widgetti/solara
6
6
  Project-URL: Documentation, https://solara.dev
@@ -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=Zu6LSrb1qgfl7PM3VPEd1douEumLCzgLPZYpG8ZctT8,3647
4
- solara/__main__.py,sha256=pm79jfba-0ZapLR0PtwZfMeiTHrLz8kEt79EygRyXxQ,24828
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=iFjmklw3uKkGPxnf5Hn6JQQ1Nw6sfAICLmkPYJEmbbE,5068
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=-00MlyWGIBw9tcDK9Cn0y-kWCI8LKP8sEsz-GAFKbgE,19871
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=ipORZbxyK8a73g8vTWiAjj2NbWY2hwoi83zRmMpuShQ,3195
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.51.0.data/data/etc/jupyter/jupyter_notebook_config.d/solara.json,sha256=3UhTBQi6z7F7pPjmqXxfddv79c8VGR9H7zStDLp6AwY,115
460
- solara_ui-1.51.0.data/data/etc/jupyter/jupyter_server_config.d/solara.json,sha256=D9J-rYxAzyD5GOqWvuPjacGUVFHsYtTfZ4FUbRzRvIA,113
461
- solara_ui-1.51.0.dist-info/METADATA,sha256=Rov3kdktbmJl6EUOQ4vhpfN49M6xt5COtnu5cjoqb-g,7459
462
- solara_ui-1.51.0.dist-info/WHEEL,sha256=C2FUgwZgiLbznR-k0b_5k3Ai_1aASOXDss3lzCUsUug,87
463
- solara_ui-1.51.0.dist-info/licenses/LICENSE,sha256=fFJUz-CWzZ9nEc4QZKu44jMEoDr5fEW-SiqljKpD82E,1086
464
- solara_ui-1.51.0.dist-info/RECORD,,
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,,