def raise_exceptions(future: asyncio.Future) -> None: """Re-raise any error except CancelledError on this exception. Use this with add_done_callback on any future which is not awaited directly to prevent swallowed exceptions. """ try: future.result() except asyncio.CancelledError: pass
def coro_logger(func_name: str, future: Future) -> None: """协程异常捕获器""" try: future.result() except (ConnectionError, CancelledError): pass except Exception as ex: getLogger().exception( r"Uncaught exception in async function %s! %s", func_name, ex.__str__())
def check_for_exception(fut: asyncio.Future, bus_client: "BusClient", die=True): """Check for exceptions in returned future To be used as a callback, eg: task.add_done_callback(check_for_exception) """ with exception_handling_context(bus_client, die): if fut.exception(): fut.result()
def _done(self, future: asyncio.Future) -> None: """Evaluate result of task. Will raise exceptions from within task. """ try: future.result() except asyncio.CancelledError: pass # stop mode self.stop()
def set_status(self, message: Tuple[str, bytes, Dict[str, str]], future: asyncio.Future): """Set message status from future.""" try: # detect exception future.result() except: # noqa: E722 # message was not delivered self.q.nack(message) # do not raise in callback else: # message delivered self.q.ack(message)
def _callback_webhook_exception_check(future: asyncio.Future, url: str, close_loop: bool): # checks if sending webhook had any failures, it indicates, that command was successfully executed # but sending webhook has failed try: future.result() except RequestException as e: logger.warning(f"Sending webhook to {url} has failed due to {e}") if close_loop: logger.info("Loop will be closed") current_loop = asyncio.get_event_loop() current_loop.stop()
def __exception_handler(self, future: Future) -> None: """ Check the result of execution of a future and report any exceptions. :param future: - Future that has been completed. """ try: future.result() except CancelledError: pass except Exception: exc_type, exc_value, exc_traceback = sys.exc_info() self.__handle_exception(exc_value, exc_traceback)
def _tls_post_handshake_done( self, task: asyncio.Future, ) -> None: self._chained_pending.discard(task) try: task.result() except asyncio.CancelledError: # canceled due to closure or something similar pass except BaseException as err: self._tls_post_handshake(err) else: self._tls_post_handshake(None)
def error_handler(future: asyncio.Future): try: future.result() except asyncio.CancelledError: pass except Exception as exc: log.exception( "Erreur dans la loop de Reverb: ", exc_info=exc, ) asyncio.create_task( self.bot.send_to_owners( "Une erreur important a eu lieue dans la boucle de Reverb.\n" "Aucun rappel ne pourra être envoyé avant d'avoir redémarré le bot.\n" "Consultez les détails dans l'invité de commandes."))
async def _next_delivery(queue: asyncio.Queue, closed: asyncio.Future) -> Tuple[bytes, int]: delivery_task = asyncio.create_task(queue.get()) done, pending = await asyncio.wait((delivery_task, closed), return_when=asyncio.FIRST_COMPLETED) if delivery_task in done: delivery = delivery_task.result() return ( b"".join(body.value for body in delivery.body), delivery.deliver.delivery_tag, ) else: # `self.closed` in Done delivery_task.cancel() closed.result() # raise exception if there is one raise ChannelClosed
def _done_callback(_future: Future) -> None: nonlocal results if _future.exception() is None: segment, status, flag = _future.result() if flag is None: segment.content = [] # logger.error('下载过程中出现已知异常 需重新下载\n') elif flag is False: segment.content = [] # 某几类已知异常 如状态码不对 返回头没有文件大小 视为无法下载 主动退出 cancel_all_task() if status in ['STATUS_CODE_ERROR', 'NO_CONTENT_LENGTH']: logger.error( f'{status} {t_msg.segment_cannot_download}') elif status == 'EXIT': pass else: logger.error( f'{status} {t_msg.segment_cannot_download_unknown_status}' ) results[segment] = flag if self.xprogress.is_ending(): cancel_uncompleted_task() else: # 出现未知异常 强制退出全部task logger.error( f'{t_msg.segment_cannot_download_unknown_exc} => {_future.exception()}\n' ) cancel_all_task() results['未知segment'] = False
def run_until_complete(self, future: asyncio.Future) -> Any: self._check_running() new_task = False if not asyncio.isfuture(future): future = asyncio.ensure_future(future, loop=self) # We wrapped `future` in a new Task since it was not a Future. new_task = True # An exception is raised if the new task doesn't complete, so there is no need to log the "destroy # pending task" message. future._log_destroy_pending = False else: if _helpers.get_future_loop(future) is not self: raise ValueError("Future does not belong to this loop") future.add_done_callback(_run_until_complete_cb) try: self._run_mainloop() except: if new_task and future.done() and not future.cancelled(): # The coroutine raised a BaseException. Consume the exception to not log a warning (Future # will log a warning if its exception is not retrieved), the caller doesn't have access to the # task wrapper we made. future.exception() raise finally: future.remove_done_callback(_run_until_complete_cb) if not future.done(): raise RuntimeError('Event loop stopped before Future completed.') return future.result()
async def get(self, timeout=None) -> Connection: async with self._alock: if len(self._idle_pool) > 0: c = self._idle_pool.pop() self._using_pool.add(c) _connectionCtxVar.set(c) return c if len(self._using_pool) < self._pool_size: c = await self._aopen() self._using_pool.add(c) _connectionCtxVar.set(c) return c future = Future() self._waiting.append(future) if timeout and timeout > 0: asyncio.get_event_loop().call_later(timeout, lambda: future.done()) await future c = future.result() if not c: return c _connectionCtxVar.set(c) self._using_pool.add(c) return c
def perform_request(self, method, url, headers=None, params=None, body=None): futur_result = Future(loop=self.loop) query_iterator = self.perform_async_request(futur_result, method, url, headers, params, body) (connection, next_method, next_url, next_params, next_body, next_headers, ignore, timeout) = query_iterator.send(None) while True: curl_future = Future(loop=self.loop) yield from connection.perform_request(method, next_url, next_params, next_body, headers=next_headers, ignore=ignore, future=curl_future) try: (connection, next_method, next_url, next_params, next_body, next_headers, ignore, timeout) = query_iterator.send(curl_future.result) except StopIteration: break return futur_result.result()
def _awaitable_done(self, fut: asyncio.Future): try: self.set_result(fut.result()) except asyncio.CancelledError: super().cancel() except Exception as ex: # pylint: disable=broad-except self.set_exception(ex)
def callback(step_future: asyncio.Future): del pending[step.name] result = step_future.result() if result.exception: retry_strategy = step.retry_strategy or self.retry_strategy retry_after = retry_strategy.get_retry_timeout(result.exception, attempt_no + 1) if retry_after: ctx.log.error('retrying after {} ms'.format(retry_after)) pending[step.name] = 'pending retry' def retry(retry_future): run_step(step, payload, attempt_no + 1) retry_future = self.event_loop.create_task(asyncio.sleep(retry_after / 1000)) retry_future.add_done_callback(retry) else: ctx.log.error('failed after {} attempts, not continuing this branch'.format(attempt_no)) errors[step.name] = result.exception else: for child in step.children: run_step(child, result.result) if not pending: ctx.log.info('workflow complete!') if errors: trigger_fut.set_exception(SimpleRunFailure(errors)) else: trigger_fut.set_result(None)
def _cafit_done(self, fut: asyncio.Future) -> None: if fut.cancelled(): self.cancel() if self.done(): return result: ConanFitResult = fut.result() self.left_contact = result.left_contact self.right_contact = result.right_contact self.left_angle = result.left_angle self.right_angle = result.right_angle self.left_curvature = result.left_curvature self.right_curvature = result.right_curvature self.left_arc_center = result.left_arc_center self.right_arc_center = result.right_arc_center self.left_arclengths = result.left_arclengths self.right_arclengths = result.right_arclengths self.left_residuals = result.left_residuals self.right_residuals = result.right_residuals self.left_mask = result.left_mask self.right_mask = result.right_mask self.status = ConanAnalysisStatus.FINISHED self.job_end = time.time()
def wait_for_future(future: asyncio.Future, timeout: float = None): """Waits for anon asyncio future. Helper method. Args: future (asyncio.Future): The future to wait for. timeout (float, optional): The wait timeout. Defaults to None. Returns: any: The future result. """ if asyncio.iscoroutine(future): loop = get_active_loop() future = loop.create_task(future) else: loop = get_asyncio_future_event_loop(future) if timeout is not None: if sys.version_info.minor < 10: future = asyncio.wait_for(future, timeout=timeout, loop=loop) else: future = asyncio.wait_for(future, timeout=timeout) loop.run_until_complete(future) last_exception = future.exception() if last_exception is not None: raise last_exception return future.result()
def feature_finished(self, future: asyncio.Future, reconnect_fn=None, name=''): try: self.logInfo('Feature finished: "{}"'.format(name)) if future.cancelled(): return exc = future.exception() if exc: if (isinstance(exc, ConnectionClosed) and exc.code > 1002) \ or isinstance(exc, InvalidStatusCode, TypeError): self.logError(exc) if reconnect_fn and not self.stop: self.logInfo('Trying to reconnect...') sleep(1) reconnect_fn() else: self.logInfo('No reconnection function...') return else: self.logError(exc) else: ws: WebSocketClientProtocol = future.result() if ws and ws.state == State.CLOSED: self.logInfo('WS Closed: {} - {}'.format( ws.close_code, ws.close_reason)) except: self.logError(traceback.format_exc())
def invoke(future: asyncio.Future): loop = call.manager.session.connection.manager.loop try: result = future.result() self._future = asyncio.ensure_future(self._invoke(), loop=loop) except Exception as e: print(e)
def get_device_from_message( self, ip_addr: str, future: Future) -> None: """Use for extracting the device from the broadcast message.""" msg = future.result() if msg.verified: if self._device_id == msg.device_id: if self._device: # Update known device self._device.update_device_data( ip_addr, msg.name, msg.device_state, msg.remaining_time_to_off, msg.auto_off_set, msg.power, msg.current, ( self._device.last_state_change if msg.device_state == self._device.state else datetime.now() )) else: # New device discoverd self._device = SwitcherV2Device( msg.device_id, ip_addr, msg.mac_address, msg.name, msg.device_state, msg.remaining_time_to_off, msg.auto_off_set, msg.power, msg.current, self._phone_id.lower(), self._device_password.lower(), datetime.now()) try: self._queue.put_nowait(self._device) except QueueFull: try: self._queue.get_nowait() except QueueEmpty: pass ensure_future( self._queue.put(self._device), loop=self._loop) self._accept_datagrams.set()
def error_handler(self, fut: asyncio.Future): try: fut.result() except asyncio.CancelledError: pass except Exception as exc: log.exception( "Unexpected exception occurred in background loop of RemindMe: ", exc_info=exc, ) asyncio.create_task( self.bot.send_to_owners( "An unexpected exception occurred in the background loop of RemindMe.\n" "Reminders will not be sent out until the cog is reloaded.\n" "Check your console or logs for details, and consider opening a bug report for this." ))
async def query( self, request: Callable[[], Awaitable[None]], status: asyncio.Future, *, send_interval: float = 0.2, timeout: float = 2.0, ) -> Any: """ Query :param request: :param status: :param send_interval: :param timeout: """ async def sender(): while not status.done(): await request() await asyncio.sleep(send_interval) sender = asyncio.ensure_future(sender()) try: await asyncio.wait_for(status, timeout=timeout) finally: with suppress(asyncio.CancelledError): sender.cancel() await sender return status.result()
def remove_flow(future: Future) -> None: try: future.result() # Propagates any exceptions except TimeoutError: self.client.schedule_task( member.kick(reason="Captcha timeout exceeded.")) return finally: self.flows.pop(member, None) self.client.schedule_task(member.add_roles(member_role)) self.logger.info( "Successfully completed captcha auth flow for %s adding roles: %s", str(member), repr(member_role), )
def error_handler(fut: asyncio.Future): try: fut.result() except asyncio.CancelledError: pass except Exception as exc: # pylint: disable=broad-except log.exception( "Unexpected exception occurred in background loop of Heartbeat: ", exc_info=exc, ) asyncio.create_task( self.bot.send_to_owners( "An unexpected exception occurred in the background loop of Heartbeat.\n" "Heartbeat pings will not be sent until Heartbeat is reloaded.\n" "Check your console or logs for details, and consider opening a bug report for this." ))
def when_task_finished(fut: asyncio.Future): self._running_commands.remove(fut) try: # Retrieve any error which may have occurred. # We ignore the error because we assume any exceptions which the # handler threw will have already been placed into the error queue # by the queue_exception_checker(). # Regardless, we must retrieve the result in order to keep Python happy. fut.result() except: pass # We use call_soon_threadsafe() to ensure we call the Event's set() # in a threadsafe fashion. This is because the Event object may have # been created in another thread and be attached to another event loop on_done._loop.call_soon_threadsafe(on_done.set)
def _on_result(future: asyncio.Future, new_future: asyncio.Future = None): if not new_future.done(): exc = future.exception() if exc: return new_future.set_exception(exc) new_future.set_result(future.result())
def _done(self, future: asyncio.Future): try: result = future.result() except Exception: # pylint: disable=broad-except self._error_callback(*sys.exc_info()) else: if result != NONE: Publisher.notify(self, result)
def on_widget_created(self, f: Future): """Using Snackbar.make returns async so we have to initialize it later. """ snackbar_id = f.result() self.widget = Snackbar(__id__=snackbar_id) self.init_widget()
def executor_finished(name: str, future: Future) -> None: """Set status with default callback for executors.""" active_executors = json.loads( redis_client.get(f"atlas_hub_executors-{current_user.id}") or json.dumps({})) active_executors[name + "-done"] = future.result() redis_client.set(f"atlas_hub_executors-{current_user.id}", json.dumps(active_executors))
def doreqcb(self, jobh: asyncio.Future): fures = jobh.result() res = fures[2] req = fures[1] reqid = fures[0] # qDebug(str(res.status_code) + ', ' + str(res.headers)) self._res_map[reqid] = [req, res] self._req_map.pop(reqid) self.reqFinished.emit(reqid) return
def _inner(fut: asyncio.Future): result = fut.result() # type: Response # Get the H2State for this request. state = self.streams[stream_id] # type: H2State # Get the app iterator. it = result(environ, state.start_response) headers = state.get_response_headers() # Send the headers. self.conn.send_headers(stream_id, headers, end_stream=False) # Place all the data from the app iterator on the queue. for i in it: self.stream_data[stream_id].put_nowait(i) # Add the sentinel value. self.stream_data[stream_id].put_nowait(REQUEST_FINISHED)
class SubscriberThread(threading.Thread): def __init__(self, topic, id): super().__init__(target=self) self.subscriber = Subscriber(topic=topic, id=id) self.future = Future() def done(self): return self.future.done() def result(self): return self.future.result() def run(self): try: self.subscriber.open() result = self.loop() self.future.set_result(result) except Exception as error: self.future.set_exception(error) finally: self.subscriber.close() def loop(self): raise NotImplementedError()
class ClientProtocolMixin(Protocol): """ To use, inherit also from CyClientBase You cannot inherit from it here to avoid two classes with predefined structure inheriting and resulting in an error """ ACK_TIMEOUT_SECONDS = 1.0 ACK_TIMEOUT = 'ACK_TIMEOUT' MISSED_MESSAGES_BEFORE_REREGISTRATION = 2 def __init__(self, verbose, dump, ticks_per_second, csv_writer_factory=None): Protocol.__init__(self) self._ticks_per_second = ticks_per_second self.last_samples_received = None self.cylib = EmotoolCylib( parent=self, verbose=verbose, dump=dump, csv_writer_factory=csv_writer_factory) self.futures = Futures() self.reset_ack() self.connection_made_future = self.futures.add_future() self._reset_task = None self.start_check_progress() def set_future_result(self, future, result): self.futures.set_future_result(future, result) def connection_made(self, transport): self.transport = transport self.cylib.parser.set_transport(transport) self.set_future_result(self.connection_made_future, self) def connection_lost(self, exc): # generally, what do we want to do at this point? it could mean USB was unplugged, actually has to be? if client stops # this wouldn't happen - we wouldn't notice at this level. So quit? #self._debug_log("serial connection_lost") pass def exit_gracefully(self): self.futures.cancel_all() def send_message(self, msg_type, **kw): self.cylib.parser.send_message(msg_type, **kw) self.ack = self.futures.add_future(timeout=self.ACK_TIMEOUT_SECONDS, timeout_result=self.ACK_TIMEOUT) def reset_ack(self): self.ack = Future() self.ack.set_result(True) async def await_ack(self): try: await self.ack except Exception as e: import pdb; pdb.set_trace() # XXX sometimes result is not available. Probably as a result of an ack # being set to a new one. Treat it as no timeout. try: result = self.ack.result() except: result = None is_timeout = result == self.ACK_TIMEOUT self.reset_ack() if is_timeout: print("timeout {}".format(repr(self.futures._futures))) raise AckTimeout() async def send_set_variables(self, variables): await self.send_sampler_clear() self.cylib.sampler.clear() for d in variables: logger.info("Sending 'Register variable': {}".format(repr(d))) await self._send_sampler_register_variable( phase_ticks=d['phase_ticks'], period_ticks=d['period_ticks'], address=d['address'], size=d['size'] ) self.cylib.sampler.register_variables(variables) self._variables = variables async def send_sampler_clear(self): await self.send_and_ack(SamplerClear) async def _send_sampler_register_variable(self, phase_ticks, period_ticks, address, size): await self.send_and_ack(SamplerRegisterVariable, phase_ticks=phase_ticks, period_ticks=period_ticks, address=address, size=size) async def send_sampler_clear(self): await self.send_and_ack(SamplerClear) async def send_sampler_start(self): await self.send_and_ack(SamplerStart) self.cylib.sampler.on_started() async def send_sampler_stop(self): await self.send_and_ack(SamplerStop) self.cylib.sampler.on_stopped() def start_check_progress(self): if self._reset_task is not None: return self._reset_task = get_event_loop().create_task(self.check_progress()) async def check_progress(self): loop = get_event_loop() while True: if not self.cylib.sampler.running: # remain until we start running await sleep(0.01) continue dt = (self.MISSED_MESSAGES_BEFORE_REREGISTRATION * float(self.cylib.sampler.max_ticks_between_messages()) / self._ticks_per_second) dt = max(dt, 0.1) #print("DEBUG {time()}: check_progress: new/old/dt {self.samples_received}/{last_samples_received} {dt}") redo_registration = self.samples_received == self.last_samples_received self.last_samples_received = self.samples_received if redo_registration: print("DEBUG {now}: redoing registration, samples {received}".format( now=time(), received=self.samples_received)) await self.redo_registration_and_start() # regardless of redo, we continue to monitor (until stopped) #print("DEBUG: check_progress: sleeping {time()}") await sleep(dt) async def redo_registration_and_start(self): while True: try: await self.send_sampler_stop() await self.send_set_variables(self._variables) await self.send_sampler_start() break except AckTimeout: pass async def send_version(self): # We don't tell our version to the embedded right now - it doesn't care # anyway await self.send_after_last(Version) async def send_after_last(self, msg_type, **kw): """ We are running in asyncio We must await an ack from the embedded. That is the protocol and importantly the embedded has a tiny 16 byte buffer so it cannot handle more than a message at a time. """ await self.await_ack() self.send_message(msg_type, **kw) async def send_and_ack(self, msg_type, **kw): await self.send_after_last(msg_type, **kw) await self.await_ack()
def cb(future: asyncio.Future): res = future.result() if res.success: f(res).relay_result(wrapper) else: wrapper.cancel()
def setter(f: asyncio.Future): wrapper.set_result(f.result())