""" Threading utilities for PyQt5 asynchronous operations """ from PyQt5.QtCore import QThread, pyqtSignal, QObject from typing import Callable, Any, Optional import traceback from .logger import setup_logger logger = setup_logger() class WorkerSignals(QObject): """Signals for worker threads""" started = pyqtSignal() finished = pyqtSignal(object) # Result error = pyqtSignal(str, str) # Error message, traceback progress = pyqtSignal(int, str) # Progress percent, status message class Worker(QThread): """ Generic worker thread for running tasks in background Usage: worker = Worker(my_function, arg1, arg2, kwarg1=value1) worker.signals.finished.connect(on_finished) worker.signals.error.connect(on_error) worker.start() """ def __init__(self, func: Callable, *args, **kwargs): """ Initialize worker Args: func: Function to execute *args: Positional arguments for func **kwargs: Keyword arguments for func """ super().__init__() self.func = func self.args = args self.kwargs = kwargs self.signals = WorkerSignals() self.result = None def run(self): """Execute the function in background thread""" try: logger.debug(f"Worker started: {self.func.__name__}") self.signals.started.emit() # Execute function self.result = self.func(*self.args, **self.kwargs) # Emit success self.signals.finished.emit(self.result) logger.debug(f"Worker finished: {self.func.__name__}") except Exception as e: # Emit error error_msg = str(e) error_tb = traceback.format_exc() logger.error(f"Worker error in {self.func.__name__}: {error_msg}\n{error_tb}") self.signals.error.emit(error_msg, error_tb) class UpdateWorker(Worker): """ Specialized worker for series updates with progress reporting This worker extends the base Worker to provide progress updates during long-running scraping operations. """ def __init__(self, func: Callable, *args, **kwargs): super().__init__(func, *args, **kwargs) def report_progress(self, percent: int, message: str): """ Report progress (can be called from within the worker function) Args: percent: Progress percentage (0-100) message: Status message """ self.signals.progress.emit(percent, message) logger.debug(f"Progress: {percent}% - {message}")