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 +1 -1
- solara/server/starlette.py +2 -2
- solara/server/static/solara_bootstrap.py +1 -1
- solara/tasks.py +62 -5
- solara/website/pages/changelog/changelog.md +10 -0
- {solara_ui-1.45.0.dist-info → solara_ui-1.46.0.dist-info}/METADATA +1 -1
- {solara_ui-1.45.0.dist-info → solara_ui-1.46.0.dist-info}/RECORD +11 -11
- {solara_ui-1.45.0.data → solara_ui-1.46.0.data}/data/etc/jupyter/jupyter_notebook_config.d/solara.json +0 -0
- {solara_ui-1.45.0.data → solara_ui-1.46.0.data}/data/etc/jupyter/jupyter_server_config.d/solara.json +0 -0
- {solara_ui-1.45.0.dist-info → solara_ui-1.46.0.dist-info}/WHEEL +0 -0
- {solara_ui-1.45.0.dist-info → solara_ui-1.46.0.dist-info}/licenses/LICENSE +0 -0
solara/__init__.py
CHANGED
solara/server/starlette.py
CHANGED
|
@@ -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"
|
|
233
|
+
if message.get("text") is not None:
|
|
234
234
|
return message["text"]
|
|
235
|
-
elif "bytes"
|
|
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.
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
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=
|
|
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=
|
|
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=
|
|
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=
|
|
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=
|
|
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.
|
|
460
|
-
solara_ui-1.
|
|
461
|
-
solara_ui-1.
|
|
462
|
-
solara_ui-1.
|
|
463
|
-
solara_ui-1.
|
|
464
|
-
solara_ui-1.
|
|
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,,
|
|
File without changes
|
{solara_ui-1.45.0.data → solara_ui-1.46.0.data}/data/etc/jupyter/jupyter_server_config.d/solara.json
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|