diff --git a/solara/components/datatable.py b/solara/components/datatable.py index 0494785d4..66c7161c9 100644 --- a/solara/components/datatable.py +++ b/solara/components/datatable.py @@ -17,7 +17,7 @@ def _ensure_dict(d): - if dataclasses.is_dataclass(d): + if dataclasses.is_dataclass(d) and not isinstance(d, type): # is_dataclass also returns True for dataclass type, rather than instance return dataclasses.asdict(d) return d diff --git a/solara/server/shell.py b/solara/server/shell.py index dfabe31d0..19f95ccd1 100644 --- a/solara/server/shell.py +++ b/solara/server/shell.py @@ -58,9 +58,12 @@ def publish( self, data, metadata=None, + source=None, + *, # Enforce keyword-only arguments to match DisplayPublisher.publish transient=None, update=False, - ): + **kwargs, # Make sure we're compatible with DisplayPublisher.publish + ) -> None: """Publish a display-data message Parameters diff --git a/solara/tasks.py b/solara/tasks.py index 03bb1df3b..bc2df7365 100644 --- a/solara/tasks.py +++ b/solara/tasks.py @@ -1,3 +1,4 @@ +import sys import abc import asyncio import dataclasses @@ -27,6 +28,11 @@ from .toestand import Ref as ref +if sys.version_info >= (3, 8): + from typing import Literal +else: + from typing_extensions import Literal + R = TypeVar("R") T = TypeVar("T") P = typing_extensions.ParamSpec("P") @@ -686,24 +692,26 @@ def create_task(): return wrapper(f) +# Type alias required for Python <= 3.9, where ParamSpec doesn't properly support non-type arguments +# i.e. [] is taken as a value instead of a type @overload def use_task( f: None = None, *, - dependencies: None = ..., + dependencies: Literal[None] = ..., raise_error=..., prefer_threaded=..., -) -> Callable[[Callable[P, R]], Task[P, R]]: ... +) -> Callable[[Callable[[], R]], "Task[[], R]"]: ... @overload def use_task( - f: Callable[P, R], + f: Callable[[], R], *, - dependencies: None = ..., + dependencies: Literal[None] = ..., raise_error=..., prefer_threaded=..., -) -> Task[P, R]: ... +) -> "Task[[], R]": ... @overload @@ -727,12 +735,12 @@ def use_task( def use_task( - f: Union[None, Callable[P, R]] = None, + f: Union[None, Callable[[], R]] = None, *, dependencies: Union[None, List] = [], raise_error=True, prefer_threaded=True, -) -> Union[Callable[[Callable[P, R]], Task[P, R]], Task[P, R]]: +) -> Union[Callable[[Callable[[], R]], "Task[[], R]"], "Task[[], R]"]: """A hook that runs a function or coroutine function as a task and returns the result. Allows you to run code in the background, with the UI available to the user. This is useful for long running tasks, @@ -811,7 +819,7 @@ async def square(): """ def wrapper(f): - def create_task() -> Task[P, R]: + def create_task() -> Task[[], R]: return task(f, prefer_threaded=prefer_threaded) task_instance = solara.use_memo(create_task, dependencies=[]) diff --git a/tests/integration/assets_test.py b/tests/integration/assets_test.py index a2c095409..4fb3082eb 100644 --- a/tests/integration/assets_test.py +++ b/tests/integration/assets_test.py @@ -67,8 +67,9 @@ def test_assets_extra(solara_server): def test_api_style(page_session: playwright.sync_api.Page, solara_server, solara_app): # this test is added because the include css macro in the jinja template may embed the # css, which also requires respecting the extra assets directories - with solara_app("solara.website.pages.documentation.components.input.button"), extra_assets( - [str(HERE / "assets" / "assets1"), str(HERE / "assets" / "assets2")] + with ( + solara_app("solara.website.pages.documentation.components.input.button"), + extra_assets([str(HERE / "assets" / "assets1"), str(HERE / "assets" / "assets2")]), ): page_session.goto(solara_server.base_url) button = page_session.locator("text=Clicked 0 times")