def call(self, func, *args, **kwargs): """Runs the function in the main loop and blocks until it is finshed or abort() was called. In case this is called from the main loop the function gets executed immediately. The priority kwargs defines the event source priority and will not be passed to func. In case a timeout kwarg is given the call will raise MainRunnerTimeoutError in case the function hasn't been scheduled (doesn't mean returned) until that time. timeout is a float in seconds. Can raise MainRunnerError in case the function raises an exception. Raises MainRunnerAbortedError in case the runner was aborted. Raises MainRunnerTimeoutError in case the timeout was reached. """ with self._lock: if self._aborted: # Make sure we have a debug statment if we catch this error accidently logger.debug( "Ran {}| self.aborted={}".format( sys._getframe().f_code.co_name, self._aborted ) ) raise self._error # pylint: disable=raising-bad-type self._error = None # XXX: ideally this should be GLib.MainContext.default().is_owner() # but that's not available in older pygobject if is_main_thread(): kwargs.pop("priority", None) self._run(func, *args, **kwargs) else: assert self._source_id is None assert self._call_id is None timeout = kwargs.pop("timeout", None) call_event = threading.Event() self._call_id = object() self._source_id = GLib.idle_add( self._idle_run, self._call_id, call_event, func, *args, **kwargs ) # only wait for the result if we are sure it got scheduled if call_event.wait(timeout): self._cond.wait() self._call_id = None if self._source_id is not None: GLib.source_remove(self._source_id) self._source_id = None raise MainRunnerTimeoutError("timeout: %r" % timeout) if self._error is not None: raise self._error # pylint: disable=raising-bad-type return self._return
def __init__(self, func, timeout=None, owner=None, priority=None): """Timeout in milliseconds""" self.func = func self.dirty = False self.args = None if owner: def destroy_cb(owner): self.abort() owner.connect("destroy", destroy_cb) if priority is None: priority = GLib.PRIORITY_DEFAULT if timeout is None: self.do_idle_add = lambda f: GLib.idle_add(f, priority=priority) else: self.do_idle_add = lambda f: GLib.timeout_add(timeout, f, priority=priority)
def notify_observers(self, info): for obs in self._observers: event = threading.Event() GLib.idle_add(obs.update, event, info)