def __init__( self, parent, fun, on_error: str = None, use_daemon_thread: bool = True, ignore_waiting_calls_timeout: Union[timedelta, float] = None, ): super().__init__() thread_name = f"ccc_async::{fun.__module__}::{fun.__qualname__}" if parent is not None: thread_name = f"{thread_name} (oid: {id(parent)})" self.task = Task(fun, thread_name=thread_name, use_daemon_thread=use_daemon_thread) self.is_waiting_on_call = False self.was_triggered = False self.parent = parent self.invoke_error: Callable = None self.last_executed = None self.ignore_waiting_calls_timeout: timedelta = ( None if ignore_waiting_calls_timeout is None else ( ignore_waiting_calls_timeout if isinstance(ignore_waiting_calls_timeout, timedelta) else timedelta(ignore_waiting_calls_timeout) ) ) if isinstance(on_error, str): assert parent is not None, ValueError("Cannot assign on_error as string to a non class method") assert hasattr(parent, on_error), ValueError( f"Error method not found in {parent.__class__.__name__}.{on_error}" ) self.invoke_error = getattr(parent, on_error) elif on_error is not None: assert callable(on_error), ValueError("On error must be a callable or a string") self.invoke_error = on_error self.task.on(self.task.error_event_name, lambda task, ex: self.on_error(ex)) self.task.on(self.task.event_name, lambda *args, **kwargs: self.on_done())
def test_return_value_using_asyncio(): async def return_something(): return "test" assert Task(return_something, use_async_loop=True).start().join() == "test"
def test_return_value_using_thread(): def return_something(): return "test" assert Task(return_something).start().join() == "test"
handler.emit("test", "the message") from zthreading.events import EventHandler from zthreading.tasks import Task handler = EventHandler() def handle_test_event(msg: str): print("The event messge: " + msg) def run_in_a_different_thread(msg): handler.emit("test", msg) handler.on("test", handle_test_event) Task(run_in_a_different_thread).start("A message from a thread").join() from zthreading.decorators import collect_consecutive_calls_async @collect_consecutive_calls_async() def consecutive_calls_action(): # Like save this to file.. for example. # should be printed twice, once for the first call, and another for the last call. print("consecutive called action") for i in range(1, 20): consecutive_calls_action()
from random import random from time import sleep from zthreading.tasks import Task # A task is an EventHandler, and has the # on method as well. task: Task = None def invoke_timed_events(): sleep(1) for i in range(1, 10): sleep(random() / 10) task.emit("test", f"loop index {i}") task.stop_all_streams() task = Task(invoke_timed_events).start() for ev in task.stream("test"): print(f"{ev.name}, {ev.args[0]}")