diff --git a/ubuntu_smoother/utils/meson.build b/ubuntu_smoother/utils/meson.build index 7151ce0..f929c30 100644 --- a/ubuntu_smoother/utils/meson.build +++ b/ubuntu_smoother/utils/meson.build @@ -8,6 +8,7 @@ sources = [ 'flatpak.py', 'snap.py', 'configurator.py', + 'run_async.py', ] install_data(sources, install_dir: utilsdir) \ No newline at end of file diff --git a/ubuntu_smoother/utils/run_async.py b/ubuntu_smoother/utils/run_async.py new file mode 100644 index 0000000..e46c862 --- /dev/null +++ b/ubuntu_smoother/utils/run_async.py @@ -0,0 +1,70 @@ +# run_async.py +# +# Copyright 2022 brombinmirko +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, in version 3 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty 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, see . +# + +import os +import sys +import threading +import traceback +import logging + +from gi.repository import GLib + +logger = logging.getLogger("UbuntuSmoother::Async") + + +class RunAsync(threading.Thread): + """ + This class is used to execute a function asynchronously. + It takes a function, a callback and a list of arguments as input. + """ + + def __init__(self, task_func, callback=None, *args, **kwargs): + if "DEBUG_MODE" in os.environ: + import faulthandler + faulthandler.enable() + + self.source_id = None + assert threading.current_thread() is threading.main_thread() + + super(RunAsync, self).__init__(target=self.__target, args=args, kwargs=kwargs) + + self.task_func = task_func + + self.callback = callback if callback else lambda r, e: None + self.daemon = kwargs.pop("daemon", True) + + self.start() + + def __target(self, *args, **kwargs): + result = None + error = None + + logger.debug(f"Running async job [{self.task_func}].") + + try: + result = self.task_func(*args, **kwargs) + except Exception as exception: + logger.error("Error while running async job: " + f"{self.task_func}\nException: {exception}") + + error = exception + _ex_type, _ex_value, trace = sys.exc_info() + traceback.print_tb(trace) + traceback_info = '\n'.join(traceback.format_tb(trace)) + + self.source_id = GLib.idle_add(self.callback, result, error) + return self.source_id