solara-ui 1.45.0__py3-none-any.whl → 1.46.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.45.0"
3
+ __version__ = "1.46.0"
4
4
  github_url = "https://github.com/widgetti/solara"
5
5
  git_branch = "master"
6
6
 
@@ -230,9 +230,9 @@ await to_thread.run_sync(my_update)
230
230
  fut = self.portal.spawn_task(self.ws.receive)
231
231
 
232
232
  message = await asyncio.wrap_future(fut)
233
- if "text" in message:
233
+ if message.get("text") is not None:
234
234
  return message["text"]
235
- elif "bytes" in message:
235
+ elif message.get("bytes") is not None:
236
236
  return message["bytes"]
237
237
  elif message.get("type") == "websocket.disconnect":
238
238
  raise websocket.WebSocketDisconnect()
@@ -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.45.0-py2.py3-none-any.whl", keep_going=True)
122
+ await micropip.install("/wheels/solara-1.46.0-py2.py3-none-any.whl", keep_going=True)
123
123
  import solara
124
124
 
125
125
  el = solara.Warning("lala")
solara/tasks.py CHANGED
@@ -7,6 +7,7 @@ import inspect
7
7
  import logging
8
8
  import threading
9
9
  from enum import Enum
10
+ import typing
10
11
  from typing import (
11
12
  Any,
12
13
  Callable,
@@ -19,6 +20,7 @@ from typing import (
19
20
  cast,
20
21
  overload,
21
22
  )
23
+ import weakref
22
24
 
23
25
  import typing_extensions
24
26
 
@@ -35,6 +37,11 @@ else:
35
37
  from typing_extensions import Literal
36
38
 
37
39
 
40
+ # Import kernel_context for typing only
41
+ if typing.TYPE_CHECKING:
42
+ import solara.server.kernel_context
43
+
44
+
38
45
  R = TypeVar("R")
39
46
  T = TypeVar("T")
40
47
  P = typing_extensions.ParamSpec("P")
@@ -201,6 +208,7 @@ class TaskAsyncio(Task[P, R]):
201
208
  current_future: Optional[asyncio.Future] = None
202
209
  _cancel: Optional[Callable[[], None]] = None
203
210
  _retry: Optional[Callable[[], None]] = None
211
+ _context: Optional["weakref.ReferenceType[solara.server.kernel_context.VirtualKernelContext]"] = None
204
212
 
205
213
  def __init__(self, run_in_thread: bool, function: Callable[P, Coroutine[Any, Any, R]], key: str):
206
214
  self.run_in_thread = run_in_thread
@@ -249,6 +257,7 @@ class TaskAsyncio(Task[P, R]):
249
257
  import solara.server.kernel_context
250
258
 
251
259
  context = solara.server.kernel_context.get_current_context()
260
+ self._context = weakref.ref(context)
252
261
  call_event_loop = context.event_loop
253
262
  else:
254
263
  call_event_loop = _main_event_loop or asyncio.get_event_loop()
@@ -263,14 +272,32 @@ class TaskAsyncio(Task[P, R]):
263
272
  try:
264
273
  thread_event_loop.run_until_complete(current_task)
265
274
  except asyncio.CancelledError as e:
266
- call_event_loop.call_soon_threadsafe(future.set_exception, e)
275
+ try:
276
+ call_event_loop.call_soon_threadsafe(future.set_exception, e)
277
+ except Exception as e2:
278
+ if not self._is_context_closed():
279
+ logger.exception(
280
+ "error setting exception from for task %s. Original exception: %s\nReason for failing to set exception: %s",
281
+ self.function.__name__,
282
+ e,
283
+ e2,
284
+ )
267
285
  except Exception as e:
268
286
  logger.exception("error running in thread")
269
- call_event_loop.call_soon_threadsafe(future.set_exception, e)
287
+ try:
288
+ call_event_loop.call_soon_threadsafe(future.set_exception, e)
289
+ except Exception as e2:
290
+ if not self._is_context_closed():
291
+ logger.exception(
292
+ "error setting exception from for task %s. Original exception: %s\nReason for failing to set exception: %s",
293
+ self.function.__name__,
294
+ e,
295
+ e2,
296
+ )
270
297
  raise
271
298
 
272
299
  self._result.value = TaskResult[R](latest=self._last_value, _state=TaskState.STARTING)
273
- thread = threading.Thread(target=runs_in_thread)
300
+ thread = threading.Thread(target=runs_in_thread, daemon=True)
274
301
  thread.start()
275
302
  else:
276
303
  self.current_task = current_task = asyncio.create_task(self._async_run(call_event_loop, future, args, kwargs))
@@ -281,6 +308,14 @@ class TaskAsyncio(Task[P, R]):
281
308
  assert running_task is not None
282
309
  return (self.current_task == _get_current_task()) and not running_task.cancelled()
283
310
 
311
+ def _is_context_closed(self):
312
+ if self._context is None:
313
+ return False
314
+ context = self._context()
315
+ if context is None:
316
+ return False
317
+ return context.closed_event.is_set()
318
+
284
319
  async def _async_run(self, call_event_loop: asyncio.AbstractEventLoop, future: asyncio.Future, args, kwargs) -> None:
285
320
  self._start_event.wait()
286
321
 
@@ -298,12 +333,34 @@ class TaskAsyncio(Task[P, R]):
298
333
  if self.is_current() and not task_for_this_call.cancelled(): # type: ignore
299
334
  self._result.value = TaskResult[R](value=value, latest=value, _state=TaskState.FINISHED, progress=self._last_progress)
300
335
  logger.info("setting result to %r", value)
301
- call_event_loop.call_soon_threadsafe(future.set_result, value)
336
+ try:
337
+ call_event_loop.call_soon_threadsafe(future.set_result, value)
338
+ except Exception as e:
339
+ if not self._is_context_closed():
340
+ logger.exception(
341
+ "error setting result from for task %s. Original exception: %s\nReason for failing to set result: %s", self.function.__name__, e, e
342
+ )
343
+ else:
344
+ logger.debug(
345
+ "ignoring error setting result from for task %s. Original exception: %s\nReason for failing to set result: %s",
346
+ self.function.__name__,
347
+ e,
348
+ e,
349
+ )
302
350
  except Exception as e:
303
351
  if self.is_current():
304
352
  logger.exception(e)
305
353
  self._result.value = TaskResult[R](latest=self._last_value, exception=e, _state=TaskState.ERROR)
306
- call_event_loop.call_soon_threadsafe(future.set_exception, e)
354
+ try:
355
+ call_event_loop.call_soon_threadsafe(future.set_exception, e)
356
+ except Exception as e2:
357
+ # we don't know if it is still useful to show this error, so we show it regardless if the context is closed or not
358
+ logger.exception(
359
+ "error setting exception from for task %s. Original exception: %s\nReason for failing to set exception: %s",
360
+ self.function.__name__,
361
+ e,
362
+ e2,
363
+ )
307
364
  # Although this seems like an easy way to handle cancellation, an early cancelled task will never execute
308
365
  # so this code will never execute, so we need to handle this in the cancel function in __call__
309
366
  # except asyncio.CancelledError as e:
@@ -1,5 +1,15 @@
1
1
  # Solara Changelog
2
2
 
3
+ ## Version 1.45.0
4
+
5
+ * Bug Fix: Correctly handle expected websocket errors instead of logging them. [#1013](https://github.com/widgetti/solara/pull/1013)
6
+ * Bug Fix: Ensure component re-renders correctly when a reactive variable is updated from another thread during rendering. [#1030](https://github.com/widgetti/solara/pull/1030)
7
+ * Bug Fix: Allow calling async tasks from within threaded tasks. [#1029](https://github.com/widgetti/solara/pull/1029)
8
+ * Bug Fix: Replace deprecated `use_side_effect` calls with `use_effect`. [#1026](https://github.com/widgetti/solara/pull/1026)
9
+ * Bug Fix(pytest-ipywidgets): Support `pytest-playwright` version 0.7.0. [#1006](https://github.com/widgetti/solara/pull/1006)
10
+ * Docs: Ensure Twitter/OpenGraph meta tags are present on documentation pages. [#998](https://github.com/widgetti/solara/pull/998)
11
+ * Breaking change: Drop support for Python 3.6 due to CI runner deprecation. [#1032](https://github.com/widgetti/solara/pull/1032)
12
+
3
13
  ## Version 1.44.0
4
14
 
5
15
  * Feature: Separate `disable_send` and `disable_input` to allow typing but not sending or vice versa for the `ChatInput` component. [86fc2ad](https://github.com/widgetti/solara/commit/86fc2ad88a89ffe134eaa6700a8c416bcab036b4).
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: solara-ui
3
- Version: 1.45.0
3
+ Version: 1.46.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,6 +1,6 @@
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=ETRGAtf8f2RuTpPEwpUnttdIUVxWwCBzmjpyBnaNmIw,3647
3
+ solara/__init__.py,sha256=XSspSdjFWrYy10EnAu0o6zS7I5XRNgsjHwW0oQzp07Q,3647
4
4
  solara/__main__.py,sha256=pm79jfba-0ZapLR0PtwZfMeiTHrLz8kEt79EygRyXxQ,24828
5
5
  solara/_stores.py,sha256=N2Ec-61XNFXwigBx8f5QYPx7gDXenCOBdmLPXiJB45E,12320
6
6
  solara/alias.py,sha256=9vfLzud77NP8in3OID9b5mmIO8NyrnFjN2_aE0lSb1k,216
@@ -20,7 +20,7 @@ solara/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
20
20
  solara/reactive.py,sha256=KN0PJl-ivxjgQj008zyPGnORo5bTNaY77uASsSW0mFQ,3430
21
21
  solara/routing.py,sha256=G_iZKozdVoUuD-qSMyuPV6jeN4qBqujAUvekw036f88,9143
22
22
  solara/settings.py,sha256=FED5SYfw1W88U8SPk9iXSgSSvMHgPkU1auONSdk5cNs,2688
23
- solara/tasks.py,sha256=cMYuh3ruTP22aoSGw5XiTjGoOn5rMF4JefMWFNqALpI,31898
23
+ solara/tasks.py,sha256=lrPvQQfAY53DQqyy4Nh1l3f5Xg0SQ7qUtHXLZ_kM1es,34564
24
24
  solara/toestand.py,sha256=pXUdvINF5x9reKL0yBdSjz-hxNkYILTsQjZVfKAYlVg,33446
25
25
  solara/util.py,sha256=UUO3BfhXb3tGP-uj8UuTYMx6kuph6PiDp4XXm-f6uyg,9697
26
26
  solara/validate_hooks.py,sha256=F0CYDOVF_23O1apJBIk9lZMq11JmkoE3BrVVT8QvZWI,9999
@@ -120,7 +120,7 @@ solara/server/reload.py,sha256=BBH7QhrV1-e9RVyNE3uz1oPj1DagC3t_XSqGPNz0nJE,9747
120
120
  solara/server/server.py,sha256=9NQcg_ncrGPQUDs50-jJGdzhlub3G3dsgcBjxqrIxX0,17120
121
121
  solara/server/settings.py,sha256=tXXpoK5CBBDbuRSMiert6UKpzMQaDbsBfyoX1Hk8iLM,7599
122
122
  solara/server/shell.py,sha256=eLrpTAw3j_1pU-2S7_Jzd4xkoSs_CA7Nv7w0Q7IVLUM,9333
123
- solara/server/starlette.py,sha256=OtUiCV3VoqsfUaRI0jyojxDfZvj4QVhr9DN7DY4s4l8,32588
123
+ solara/server/starlette.py,sha256=wchutafZy2V9lBaX3ZFfSGcARDOw6K2sti3D0XhnQGU,32616
124
124
  solara/server/telemetry.py,sha256=GPKGA5kCIqJb76wgxQ2_U2uV_s0r-1tKqv-GVxo5hs8,6038
125
125
  solara/server/threaded.py,sha256=k9k461md4MxEFX-RLit5RpVRPFlQNwr-qp5pprT8JB0,2347
126
126
  solara/server/utils.py,sha256=1Pa6HF8O1jsxDBcCWlVfP_9jFiUIQgqiIhT4oJ-iUmo,1207
@@ -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=czQrpaCPRQSA4n7q6lOD0G4Bem6jv957ZzxjLOR1pns,3195
149
+ solara/server/static/solara_bootstrap.py,sha256=YOt-aZ55ffhLPfPzfYZKTm-KAAPvB4KHlhmKQ1FDuoI,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
@@ -222,7 +222,7 @@ solara/website/pages/apps/multipage/page1.py,sha256=5hK0RZ8UBBOaZcPKaplbLeb0Vvae
222
222
  solara/website/pages/apps/multipage/page2.py,sha256=uRJ8YPFyKy7GR_Ii8DJSx3akb3H15rQAJZETMt9jVEk,1422
223
223
  solara/website/pages/careers/__init__.py,sha256=_aaO9YQOvy8JE9PYkWeSNzLU4pUU-PJMAaYy07YbKsU,1479
224
224
  solara/website/pages/changelog/__init__.py,sha256=0ouQpbt5EGEY6bHmSMt6S7Gk71gAmuaIuevT5wEE2zQ,277
225
- solara/website/pages/changelog/changelog.md,sha256=LlHUxQiXgf_UH4dXanEkgp2wc59MF5KjGJE__eS0Er4,27079
225
+ solara/website/pages/changelog/changelog.md,sha256=rmu461GhH_EsBn4GjypFAn6grGyzpC2Y3UO-84esGuA,28065
226
226
  solara/website/pages/contact/__init__.py,sha256=NkjxJo258RTHLFPQ18IVZ9euS_vJciHUrM4o1fz9QJE,1259
227
227
  solara/website/pages/documentation/__init__.py,sha256=lv9cleVukKDLKRtjTYIlfBDi8Aw3bEz2iV8-IxBz3LA,5563
228
228
  solara/website/pages/documentation/advanced/__init__.py,sha256=bLLvasuqVVWJxGN89m77ChZhDivEhVavw9-_CiG3IZA,414
@@ -456,9 +456,9 @@ solara/widgets/vue/gridlayout.vue,sha256=hk10RsEQBxkknTmqa0wtBia9LWQGdDsXlejnAj7
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.45.0.data/data/etc/jupyter/jupyter_notebook_config.d/solara.json,sha256=3UhTBQi6z7F7pPjmqXxfddv79c8VGR9H7zStDLp6AwY,115
460
- solara_ui-1.45.0.data/data/etc/jupyter/jupyter_server_config.d/solara.json,sha256=D9J-rYxAzyD5GOqWvuPjacGUVFHsYtTfZ4FUbRzRvIA,113
461
- solara_ui-1.45.0.dist-info/METADATA,sha256=_TqYXgdyCVETIAwUyLImkCBV4VxaNrO5gqWPy3koFLE,7459
462
- solara_ui-1.45.0.dist-info/WHEEL,sha256=C2FUgwZgiLbznR-k0b_5k3Ai_1aASOXDss3lzCUsUug,87
463
- solara_ui-1.45.0.dist-info/licenses/LICENSE,sha256=fFJUz-CWzZ9nEc4QZKu44jMEoDr5fEW-SiqljKpD82E,1086
464
- solara_ui-1.45.0.dist-info/RECORD,,
459
+ solara_ui-1.46.0.data/data/etc/jupyter/jupyter_notebook_config.d/solara.json,sha256=3UhTBQi6z7F7pPjmqXxfddv79c8VGR9H7zStDLp6AwY,115
460
+ solara_ui-1.46.0.data/data/etc/jupyter/jupyter_server_config.d/solara.json,sha256=D9J-rYxAzyD5GOqWvuPjacGUVFHsYtTfZ4FUbRzRvIA,113
461
+ solara_ui-1.46.0.dist-info/METADATA,sha256=d8_lsqGcyQyk7ZSXL2364Y0OT1_dPu6W-2BEdQPXrrE,7459
462
+ solara_ui-1.46.0.dist-info/WHEEL,sha256=C2FUgwZgiLbznR-k0b_5k3Ai_1aASOXDss3lzCUsUug,87
463
+ solara_ui-1.46.0.dist-info/licenses/LICENSE,sha256=fFJUz-CWzZ9nEc4QZKu44jMEoDr5fEW-SiqljKpD82E,1086
464
+ solara_ui-1.46.0.dist-info/RECORD,,