From 2bd9071f9d173316951c2a892eafb7426b791186 Mon Sep 17 00:00:00 2001 From: Iisakki Rotko Date: Fri, 7 Feb 2025 16:05:55 +0100 Subject: [PATCH] feat: deprecate use_thread (#949) --- solara/__init__.py | 1 + solara/hooks/use_thread.py | 3 +- solara/lab/__init__.py | 23 +++++++++++++- solara/tasks.py | 16 +++++----- solara/util.py | 31 +++++++++++++++++++ solara/website/pages/__init__.py | 2 ++ .../{components/lab => api/hooks}/use_task.py | 3 +- .../documentation/api/hooks/use_thread.md | 4 ++- .../documentation/api/hooks/use_thread.py | 2 +- .../{components/lab => api/utilities}/task.py | 3 +- 10 files changed, 72 insertions(+), 16 deletions(-) rename solara/website/pages/documentation/{components/lab => api/hooks}/use_task.py (70%) rename solara/website/pages/documentation/{components/lab => api/utilities}/task.py (71%) diff --git a/solara/__init__.py b/solara/__init__.py index 42e6c879a..8608b4fd8 100644 --- a/solara/__init__.py +++ b/solara/__init__.py @@ -63,6 +63,7 @@ def _using_solara_server(): from .autorouting import generate_routes, generate_routes_directory, RenderPage, RoutingProvider, DefaultLayout from .checks import check_jupyter from .scope import get_kernel_id, get_session_id +from .tasks import task, use_task, Task, TaskResult def display(*objs, **kwargs): diff --git a/solara/hooks/use_thread.py b/solara/hooks/use_thread.py index 20f083744..b10262589 100644 --- a/solara/hooks/use_thread.py +++ b/solara/hooks/use_thread.py @@ -7,13 +7,14 @@ import solara from solara.datatypes import Result, ResultState -from solara.util import cancel_guard, nullcontext +from solara.util import cancel_guard, nullcontext, deprecated SOLARA_ALLOW_OTHER_TRACER = os.environ.get("SOLARA_ALLOW_OTHER_TRACER", False) in (True, "True", "true", "1") T = TypeVar("T") logger = logging.getLogger("solara.hooks.use_thread") +@deprecated("`use_thread` is deprecated, use the more modern and performant `use_task` or `Task` instead", category=FutureWarning) def use_thread( callback: Union[ Callable[[threading.Event], T], diff --git a/solara/lab/__init__.py b/solara/lab/__init__.py index 9d92c6b10..5eb69e7d8 100644 --- a/solara/lab/__init__.py +++ b/solara/lab/__init__.py @@ -18,8 +18,9 @@ ) from .utils import cookies, headers from ..lifecycle import on_kernel_start -from ..tasks import task, use_task, Task, TaskResult +from ..tasks import task as _task, use_task as _use_task, Task as _Task, TaskResult as _TaskResult from ..toestand import computed +from ..util import deprecated __all__ = [ @@ -49,6 +50,26 @@ ] +@deprecated("solara.lab.task has been moved out of the lab namespace, use solara.task instead") +def task(*args, **kwargs): + _task(*args, **kwargs) + + +@deprecated("solara.lab.use_task has been moved out of the lab namespace, use solara.use_task instead") +def use_task(*args, **kwargs): + return _use_task(*args, **kwargs) + + +@deprecated("solara.lab.Task has been moved out of the lab namespace, use solara.Task instead") +class Task(_Task): + pass + + +@deprecated("solara.lab.TaskResult has been moved out of the lab namespace, use solara.TaskResult instead") +class TaskResult(_TaskResult): + pass + + def __getattr__(name): # for backwards compatibility from solara.components.cross_filter import ( # noqa: F401 diff --git a/solara/tasks.py b/solara/tasks.py index 8960b03cb..ad7e1fd68 100644 --- a/solara/tasks.py +++ b/solara/tasks.py @@ -543,7 +543,7 @@ def task( ```solara import asyncio import solara - from solara.lab import task + from solara import task @task async def fetch_data(): @@ -572,7 +572,7 @@ def Page(): ```solara import time import solara - from solara.lab import task + from solara import task @task def fetch_data(): @@ -611,7 +611,7 @@ def Page(): ```solara import time import solara - from solara.lab import task + from solara import task @task @@ -648,7 +648,7 @@ def Page(): ```solara import time import solara - from solara.lab import task + from solara import task @task @@ -750,7 +750,7 @@ def use_task( def use_task( f: Union[None, Callable[[], R]] = None, *, - dependencies: Union[None, List] = [], + dependencies: Union[None, List] = None, raise_error=True, prefer_threaded=True, ) -> Union[Callable[[Callable[[], R]], "Task[[], R]"], "Task[[], R]"]: @@ -771,7 +771,7 @@ def use_task( ```solara import time import solara - from solara.lab import use_task, Task + from solara import use_task, Task @solara.component @@ -798,7 +798,7 @@ def square(): ```solara import asyncio import solara - from solara.lab import use_task, Task + from solara import use_task, Task @solara.component @@ -820,7 +820,7 @@ async def square(): ## Arguments - `f`: The function or coroutine to run as a task. - - `dependencies`: A list of dependencies that will trigger a rerun of the task when changed, the task will run automatically execute when the `dependencies=None` + - `dependencies`: A list of dependencies that will trigger a rerun of the task when changed, the task will not automatically execute when the `dependencies=None`. - `raise_error`: If true, an error in the task will be raised. If false, the error should be handled by the user and is available in the `.exception` attribute of the task result object. - `prefer_threaded` - bool: Will run coroutine functions as a task in a thread when threads are available. diff --git a/solara/util.py b/solara/util.py index c3fffa8ce..fa7de2a84 100644 --- a/solara/util.py +++ b/solara/util.py @@ -11,6 +11,7 @@ from pathlib import Path from typing import TYPE_CHECKING, Dict, List, Optional, Tuple, Union from urllib.parse import urlencode +import warnings if TYPE_CHECKING: import numpy as np @@ -346,3 +347,33 @@ def wrapper(): return return_value return wrapper + + +def deprecated(reason: str, category=DeprecationWarning): + """ + Mark functions as deprecated. When the function is called, a warning is shown with the provided reason. + + Parameters + ---------- + + reason : str + The message to display when the deprecated function is used. + category : type, optional + The warning category to use, defaults to DeprecationWarning. Use DeprecationWarning when users do not need to see + the warning, and FutureWarning when users should see the warning. + + """ + + def decorator(func): + @functools.wraps(func) + def wrapped(*args, **kwargs): + warnings.warn( + reason, + category=category, + stacklevel=2, # this way we show the line where the function is called + ) + return func(*args, **kwargs) + + return wrapped + + return decorator diff --git a/solara/website/pages/__init__.py b/solara/website/pages/__init__.py index fc1b0377d..4d905feca 100644 --- a/solara/website/pages/__init__.py +++ b/solara/website/pages/__init__.py @@ -209,6 +209,8 @@ "/api/widget": "/documentation/api/utilities/widget", "/api/default_layout": "/documentation/components/layout", "/api/title": "/documentation/components/page/title", + "/documentation/components/lab/use_task": "/documentation/api/hooks/use_task", + "/documentation/components/lab/task": "/documentation/api/utilities/task", } diff --git a/solara/website/pages/documentation/components/lab/use_task.py b/solara/website/pages/documentation/api/hooks/use_task.py similarity index 70% rename from solara/website/pages/documentation/components/lab/use_task.py rename to solara/website/pages/documentation/api/hooks/use_task.py index 1e2d63480..f0839eeeb 100644 --- a/solara/website/pages/documentation/components/lab/use_task.py +++ b/solara/website/pages/documentation/api/hooks/use_task.py @@ -2,10 +2,9 @@ import solara import solara.autorouting -import solara.lab from solara.website.components import NoPage from solara.website.utils import apidoc title = "use_task" Page = NoPage -__doc__ += apidoc(solara.lab.use_task) # type: ignore +__doc__ += apidoc(solara.use_task) # type: ignore diff --git a/solara/website/pages/documentation/api/hooks/use_thread.md b/solara/website/pages/documentation/api/hooks/use_thread.md index 4055de8b0..fa45a2d34 100644 --- a/solara/website/pages/documentation/api/hooks/use_thread.md +++ b/solara/website/pages/documentation/api/hooks/use_thread.md @@ -1,4 +1,6 @@ -# use_thread +# use_thread (deprecated) + +### use_thread is deprecated, use [use_task](/documentation/api/hooks/use_task) or [Task](/documentation/api/utilities/task) instead ```python def use_thread( diff --git a/solara/website/pages/documentation/api/hooks/use_thread.py b/solara/website/pages/documentation/api/hooks/use_thread.py index bf6dfa723..3c977c2df 100644 --- a/solara/website/pages/documentation/api/hooks/use_thread.py +++ b/solara/website/pages/documentation/api/hooks/use_thread.py @@ -6,7 +6,7 @@ from solara.alias import rw HERE = Path(__file__).parent -title = "use_thread" +title = "use_thread (deprecated)" __doc__ = open(HERE / "use_thread.md").read() diff --git a/solara/website/pages/documentation/components/lab/task.py b/solara/website/pages/documentation/api/utilities/task.py similarity index 71% rename from solara/website/pages/documentation/components/lab/task.py rename to solara/website/pages/documentation/api/utilities/task.py index 5babb7c44..7fd8e0a9a 100644 --- a/solara/website/pages/documentation/components/lab/task.py +++ b/solara/website/pages/documentation/api/utilities/task.py @@ -2,10 +2,9 @@ import solara import solara.autorouting -import solara.lab from solara.website.components import NoPage from solara.website.utils import apidoc title = "Task" Page = NoPage -__doc__ += apidoc(solara.lab.task) # type: ignore +__doc__ += apidoc(solara.task) # type: ignore