# # Copyright (C) 2018 Red Hat, Inc. # # This copyrighted material is made available to anyone wishing to use, # modify, copy, or redistribute it subject to the terms and conditions of # the GNU General Public License v.2, or (at your option) any later version. # This program is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY expressed or implied, including the implied warranties of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General # Public License for more details. You should have received a copy of the # GNU General Public License along with this program; if not, write to the # Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA # 02110-1301, USA. Any Red Hat trademarks that are incorporated in the # source code or documentation are not subject to the GNU General Public # License and may only be used or replicated with the express permission of # Red Hat, Inc. # from abc import ABC, abstractmethod from threading import Lock from pyanaconda.core.signal import Signal from pyanaconda.core.async_utils import async_action_nowait __all__ = ['ProgressReporter'] class ProgressReporter(ABC): """Abstract class that allows to report a progress of a task.""" def __init__(self): super().__init__() self._progress_changed_signal = Signal() self._category_changed_signal = Signal() self.__progress_lock = Lock() self.__progress_step = 0 self.__progress_category = None self.__progress_msg = "" @property def progress(self): """Current progress of the task. :returns: tuple (step, description). """ with self.__progress_lock: return self.__progress_step, self.__progress_msg @property @abstractmethod def steps(self): """Number of progress steps in the task.""" return 0 @property def progress_changed_signal(self): """Signal emits when the progress of the task changes.""" return self._progress_changed_signal @property def category_changed_signal(self): """Signal emits when the category of the task changes.""" return self._category_changed_signal @async_action_nowait def report_category(self, category): if category is None: return else: self._category_changed_signal.emit(category) @async_action_nowait def report_progress(self, message, step_number=None, step_size=None): """Report a progress change. Update the progress and emit the progress changed signal. The next step will never be higher then self.steps and lower then the current step. By default, the step doesn't change. This is a thread safe method. :param message: Short description of the actual step. :type message: str :param step_number: The number of the next step. :type step_number: int or None :param step_size: The size of the next step. :type step_size: int or None """ with self.__progress_lock: current_step = self.__progress_step max_step = self.steps step = current_step if step_number is not None: step = step_number if step_size is not None: step += step_size if step < current_step: step = current_step if step > max_step: step = max_step self.__progress_step = step self.__progress_msg = message self._progress_changed_signal.emit(step, message)