diff --git a/magicclass/_gui/_base.py b/magicclass/_gui/_base.py index 852b13e9..92367767 100644 --- a/magicclass/_gui/_base.py +++ b/magicclass/_gui/_base.py @@ -1359,8 +1359,6 @@ def convert_attributes( return _dict -# def _find_callback_level() - _dummy_macro = DummyMacro() diff --git a/magicclass/_gui/_macro_utils.py b/magicclass/_gui/_macro_utils.py index e1d6c5b4..ce1ca7b5 100644 --- a/magicclass/_gui/_macro_utils.py +++ b/magicclass/_gui/_macro_utils.py @@ -224,7 +224,7 @@ def _func(self, *args, **kwargs): @functools_wraps(_func) def _silent(bgui: MagicTemplate, *args, **kwargs): - with bgui._search_parent_magicclass().macro.blocked(): + with bgui.macro.blocked(): out = _func.__get__(bgui)(*args, **kwargs) return out diff --git a/magicclass/ext/dask/progress.py b/magicclass/ext/dask/progress.py index 08dc28eb..2c189276 100644 --- a/magicclass/ext/dask/progress.py +++ b/magicclass/ext/dask/progress.py @@ -84,13 +84,6 @@ def _finish(self, dsk=None, state=None, errored=None): self._thread_timer.join() return None - def _on_timer_updated(self, _=None): - if self._timer.sec < 3600: - self.time_label.value = self._timer.format_time("{min:0>2}:{sec:0>2}") - else: - self.time_label.value = self._timer.format_time() - return None - def set_worker(self, worker: GeneratorWorker | FunctionWorker): """Set currently running worker.""" self._worker = worker diff --git a/magicclass/fields/_fields.py b/magicclass/fields/_fields.py index 1050cc0e..97e744e5 100644 --- a/magicclass/fields/_fields.py +++ b/magicclass/fields/_fields.py @@ -516,6 +516,8 @@ def connect_async(self, func=None, *, timeout=0.0, ignore_errors=False): from magicclass.utils import thread_worker def _wrapper(fn): + if isinstance(fn, thread_worker): + return self.connect(fn) _running = None _last_run = 0.0 diff --git a/magicclass/utils/qthreading/thread_worker.py b/magicclass/utils/qthreading/thread_worker.py index 8a21353e..1f892109 100644 --- a/magicclass/utils/qthreading/thread_worker.py +++ b/magicclass/utils/qthreading/thread_worker.py @@ -114,6 +114,9 @@ def __init__( self._ignore_errors = ignore_errors self._objects: dict[int, BaseGui] = {} self._progressbars: dict[int, ProgressBarLike | None] = {} + # recordable -> _recorder is a recording function + # not recordable, recursive=True -> _recorder is _silent + # not recordable, recursive=False -> _recorder is None self._recorder: Callable[_P, Any] | None = None self._validators: dict[str, Callable] | None = None self._signature_cache = None @@ -216,13 +219,10 @@ def callback(callback: Callable[_P, _R] = lambda: None) -> Callback[_P, _R]: raise TypeError(f"{callback} is not callable.") return Callback(callback) - @staticmethod - def run(meth: AsyncMethod[_P, _R]) -> Callable[_P, _R]: - return meth.arun - @classmethod @contextmanager def blocking_mode(cls): + """Always run thread workers in the blocking mode.""" cls._BLOCKING_SOURCES.append(None) try: yield @@ -306,9 +306,9 @@ def __get__(self, gui, objtype=None): self._objects[gui_id] = _create_worker # cache return _create_worker - def button(self, gui: BaseGui) -> Clickable: - """The corresponding button object.""" - return gui[self._func.__name__] + def _is_running(self, gui: BaseGui) -> bool: + btn = gui[self._func.__name__] + return getattr(btn, "running", False) def _validate_args(self, gui: BaseGui, args, kwargs) -> tuple[tuple, dict]: if self._validators is None: @@ -356,13 +356,16 @@ def _run(*args, **kwargs): return worker + def _is_non_blocking(self, gui: BaseGui) -> bool: + async_ok = self._force_async or self._is_running(gui) + not_blocking_mode = len(self._BLOCKING_SOURCES) == 0 + return async_ok and not_blocking_mode + def _create_method(self, gui: BaseGui) -> Callable[_P, None]: @_async_method @wraps(self) def _create_worker(*args, **kwargs): - _is_non_blocking = (self._force_async or self.button(gui).running) and len( - self._BLOCKING_SOURCES - ) == 0 + _is_non_blocking = self._is_non_blocking(gui) with gui.macro.blocked(): args, kwargs = self._validate_args(gui, args, kwargs)