tiqi-group / pydase

A Python library for creating remote control interfaces of Python objects.
https://pydase.readthedocs.io
MIT License
1 stars 1 forks source link

BREAKING: Replace implicit async function tasks with task decorator #150

Closed mosmuell closed 2 weeks ago

mosmuell commented 1 month ago

This merge request introduces a breaking change to how tasks are defined and managed in the pydase library. It improves task management by making task definitions more explicit and by that adding code-completion capabilities. With this update, users must add the @task decorator to define an asynchronous method as a task. The previous approach where pydase automatically generated start_<method> and stop_<method> methods for task control is now deprecated.

To align with the new @task decorator approach, users need to make changes to their existing codebase. Please follow the migration guide below to update your services.

Key Changes:

  1. Introduction of the @task decorator:

    • To define a method as a task within a class inheriting from pydase.DataService, you must now use the @task decorator.
    • This decorator should be applied to an asynchronous function that requires no arguments.
  2. Method is converted into an object with start() and stop() methods:

    • When a method is decorated with @task, it is converted into a Task object. This object provides start() and stop() methods to control task execution.
  3. Removal of start_<method> and stop_<method> method generation:

    • The old method of controlling tasks via dynamically generated start_<method> and stop_<method> methods is no longer supported.
    • Users must update their code to use the new Task object methods (start() and stop()).
  4. Redefinition of Autostart Tasks:

    • The way autostart tasks are defined has changed. Previously, users added tasks to the _autostart_tasks dictionary in the __init__ method of their pydase.DataService class.
    • Now, autostart behavior is defined directly in the @task decorator with the autostart=True argument.

Example of Updated Code:

Before:

import asyncio

import pydase

class MyService(pydase.DataService):
    def __init__(self) -> None:
        super().__init__()
        self._autostart_tasks["my_task"] = ()  # Define autostart task

    async def my_task(self):
        while True:
            # Task code
            await asyncio.sleep(1)

service = MyService()
service.start_my_task()  # Old way to start the task

After:

import asyncio

import pydase
from pydase.task.decorator import task

class MyService(pydase.DataService):
    @task(autostart=True)  # Define autostart task directly in the decorator
    async def my_task(self):
        while True:
            # Task code
            await asyncio.sleep(1)

service = MyService()
service.my_task.start()  # New way to start the task
mosmuell commented 2 weeks ago

Solves #129.