diff --git a/aleksis/core/util/celery_progress.py b/aleksis/core/util/celery_progress.py index ac48c7c56001a51696c8099950ed799c6a2a9cea..63428460be071e03a7bd5fe6fa64f706f3670cfa 100644 --- a/aleksis/core/util/celery_progress.py +++ b/aleksis/core/util/celery_progress.py @@ -1,6 +1,8 @@ -from decimal import Decimal from functools import wraps -from typing import Callable, Union +from numbers import Number +from typing import Callable, Optional + +from django.contrib import messages from celery_progress.backend import PROGRESS_STATE, AbstractProgressRecorder @@ -26,11 +28,11 @@ class ProgressRecorder(AbstractProgressRecorder): @recorded_task def do_something(foo, bar, recorder, baz=None): # ... - recorder.total = len(list_with_data) + recorder.set_progress(total=len(list_with_data)) for i, item in enumerate(list_with_data): # ... - recorder.set_progress(i + 1) + recorder.set_progress(i+1) # ... recorder.add_message(messages.SUCCESS, "All data were imported successfully.") @@ -61,42 +63,57 @@ class ProgressRecorder(AbstractProgressRecorder): def __init__(self, task): self.task = task - self.messages = [] - self.total = 100 - self.current = 0 - - def set_progress(self, current: Union[int, float], **kwargs): + self._messages = [] + self._current = 0 + self._total = 100 + + def set_progress( + self, + current: Optional[Number] = None, + total: Optional[Number] = None, + description: Optional[str] = None, + level: int = messages.INFO, + ): """Set the current progress in the frontend. The progress percentage is automatically calculated in relation to self.total. - :param current: The absolute number of processed items + :param current: The number of processed items; relative to total, default unchanged + :param total: The total number of items (or 100 if using a percentage), default unchanged + :param description: A textual description, routed to the frontend as an INFO message """ - self.current = current + if current is not None: + self._current = current + if total is not None: + self._total = total percent = 0 - if self.total > 0: - percent = (Decimal(current) / Decimal(self.total)) * Decimal(100) - percent = float(round(percent, 2)) + if self._total > 0: + percent = self._current / self._total + + if description is not None: + self._messages.append((level, description)) self.task.update_state( state=PROGRESS_STATE, meta={ - "current": current, - "total": self.total, + "current": self._current, + "total": self._total, "percent": percent, - "messages": self.messages, + "messages": self._messages, }, ) - def add_message(self, level: int, message: str): + def add_message(self, level: int, message: str) -> None: """Show a message in the progress frontend. + This method is a shortcut for set_progress with no new progress arguments, + passing only the message and level as description. + :param level: The message level (default levels from django.contrib.messages) :param message: The actual message (should be translated) """ - self.messages.append((level, message)) - self.set_progress(self.current) + self.set_progress(description=message, level=level) def recorded_task(orig: Callable, *args, **kwargs) -> app.Task: