async def __aexit__(self, *_: Any) -> None: while self._sc or self._rc: _ch, __, __ = await race( *(create_task(ch._on_sendable()) for ch in self._sc), *(create_task(ch._on_recvable()) for ch in self._rc), ) ch = _ch.result() if not ch: self._sc = {c: f for c, f in self._sc.items()} self._rc = {c: f for c, f in self._rc.items()} elif ch in self._sc: if ch.sendable(): try: ch.try_send(self._sc[ch]()) except StopSelector: break elif ch in self._rc: if ch.recvable(): try: self._rc[ch](ch.try_recv()) except StopSelector: break else: assert False
async def _merge_helper(q: Queue, end: Task, ait: AsyncIterable[Any]) -> None: ch = aiter(ait) while True: pending_take = create_task(cast(Any, ch.__anext__())) done_1, _ = await wait((end, pending_take), return_when=FIRST_COMPLETED) if pending_take in done_1: try: item = await pending_take except StopAsyncIteration: break else: if end in done_1: break else: pending_put = create_task(q.put(item)) done_2, _ = await wait((end, pending_put), return_when=FIRST_COMPLETED) if pending_put in done_2: await pending_put if end in done_2: break if end in done_1: break
async def pipe_parallel(src: Iterable[Chan[T]], dest: Iterable[Chan[T]]) -> None: """ # each item in `src` goes to each ch in `dest` `src` `dest` ------>| |------>| ------>| |------>| ------>|--->|------>| ------>| |------>| ------>| |------>| ... """ r_chans: MutableSequence[Chan[T]] = [*src] s_chans: MutableSequence[Chan[T]] = [*dest] while r_chans and s_chans: (_r_ready, _, _), (_s_ready, s_done, s_pending) = await gather( race(*(create_task(ch._on_recvable()) for ch in r_chans)), race(*(create_task(ch._on_sendable()) for ch in s_chans)), ) r_ready, s_ready = _r_ready.result(), _s_ready.result() if not r_ready or not s_ready: r_chans[:] = (c for c in r_chans if c) s_chans[:] = (c for c in s_chans if c) elif r_ready.recvable() and s_ready.sendable(): item = r_ready.try_recv() s_ready.try_send(item) await gather(*(_send(fut, item=item) for fut in chain(s_done, s_pending)))
async def pipe(src: Iterable[Chan[T]], dest: Iterable[Chan[T]]) -> None: """ # each item in `src` goes to first ready ch in `dest` `src` `dest` ------>| |------>| ------>| |------>| ------>|--->|------>| ------>| |------>| ------>| |------>| ... """ r_chans: MutableSequence[Chan[T]] = [*src] s_chans: MutableSequence[Chan[T]] = [*dest] while r_chans and s_chans: (_r_ready, _, _), (_s_ready, _, _) = await gather( race(*(create_task(ch._on_recvable()) for ch in r_chans)), race(*(create_task(ch._on_sendable()) for ch in s_chans)), ) r_ready, s_ready = _r_ready.result(), _s_ready.result() if not r_ready or not s_ready: r_chans[:] = (c for c in r_chans if c) s_chans[:] = (c for c in s_chans if c) elif r_ready.recvable() and s_ready.sendable(): s_ready.try_send(r_ready.try_recv())
async def test_7(self) -> None: @self.wg async def cont() -> bool: raise KeyError() create_task(cont()) with self.assertRaises(KeyError): await self.wg.wait()
async def test_1(self) -> None: ch = chan(int) create_task(to_chan(count_to_rep(), ch)) i = -1 async for i in ch: pass self.assertEqual(i, BIG_REP_FACTOR - 1) self.assertFalse(ch)
async def test_5(self) -> None: i = 5 for _ in range(i): async def cont() -> None: nonlocal i with self.wg: i -= 1 create_task(cont()) await self.wg.wait() self.assertEqual(i, 0)
async def event(self, event: HookEvent) -> None: if event.type == HookEventType.START: log.info(f"actyon stared: {event.action.name}") self.phase = ActyonPhase.PRODUCE self.state = ActyonState.UNKNOWN self._running = True self._future = create_task(self._spin(event.action)) elif event.type == HookEventType.AFTER_PRODUCE: self.phase = ActyonPhase.CONSUME elif event.type == HookEventType.PRELIMINARY_EMPTY: if self.state not in (ActyonState.OKAY, ActyonState.ERROR): self.state = ActyonState.WARN elif event.type in (HookEventType.NO_CONSUMER, HookEventType.NO_PRODUCER): if self.state != ActyonState.ERROR: self.state = ActyonState.WARN elif event.type == HookEventType.RESULT_PRODUCED: if self.state != ActyonState.ERROR: self.state = ActyonState.OKAY elif event.type == HookEventType.FAIL: self.state = ActyonState.ERROR elif event.type == HookEventType.END: if self.state == ActyonState.UNKNOWN: self.state = ActyonState.OKAY self._running = False if self._future is not None and not self._future.done(): await self._future log.info(f"actyon ended: {event.action.name}")
def _create_periodic_task(f: Callable[[], Coroutine[object, object, None]], period: float) -> Task[None]: async def wrapper() -> None: while True: await sleep(period) await f() return create_task(wrapper())
async def ctx_with_timeout(ttl_seconds: float, val: T, parent: Optional[Context] = None) -> Context[T]: monotonic_deadline = monotonic() + ttl_seconds ctx = _Context(val=val, deadline=monotonic_deadline) if parent is not None: parent.attach(ctx) if ttl_seconds <= 0: ctx.cancel() elif isfinite(ttl_seconds): async def cont() -> None: await sleep(ttl_seconds) ctx.cancel() create_task(cont()) return ctx
async def _upload_page(self, page: VideoUploaderPage) -> str: """ 上传分 P Args: page (VideoUploaderPage): 分 P 对象 Returns: str: 分 P 文件 ID,用于 submit 时的 $.videos[n].filename 字段使用。 """ preupload = await self._preupload(page) self.dispatch(VideoUploaderEvents.PRE_PAGE.value, {"page": page}) page_size = page.get_size() # 所有分块起始位置 chunk_offset_list = list(range(0, page_size, preupload["chunk_size"])) # 分块总数 total_chunk_count = len(chunk_offset_list) # 并发上传分块 chunk_number = 0 # 上传队列 chunks_pending = [] # 缓存 upload_id,这玩意只能从上传的分块预检结果获得 upload_id = preupload["upload_id"] for offset in chunk_offset_list: chunks_pending.insert( 0, self._upload_chunk(page, offset, chunk_number, total_chunk_count, preupload)) chunk_number += 1 while chunks_pending: tasks = [] while len(tasks) < preupload["threads"] and len( chunks_pending) > 0: tasks.append(create_task(chunks_pending.pop())) result = await asyncio.gather(*tasks) for r in result: if not r['ok']: chunks_pending.insert( 0, self._upload_chunk(page, r['offset'], r['chunk_number'], total_chunk_count, preupload)) data = await self._complete_page(page, total_chunk_count, preupload, upload_id) self.dispatch(VideoUploaderEvents.AFTER_PAGE.value, {"page": page}) return data
def __init__(self, bridge, _config=None): if _config is None: _config = config self.channels = dict() self.listener_tasks = dict() self.bridge = bridge self.send_task = create_task(self.send_worker()) self.config = _config for i in _config["channel"]: self.listen(i)
async def merge(*aits: AsyncIterable[_T]) -> AsyncIterator[_T]: ev = Event() q: Queue = Queue(maxsize=1) end = create_task(ev.wait()) g = gather(*(_merge_helper(q, end=end, ait=ait) for ait in aits)) try: while True: fut = create_task(q.get()) done, _ = await wait((g, fut), return_when=FIRST_COMPLETED) if fut in done: item = await fut yield item if g in done: break except CancelledError: await cancel(g) finally: ev.set() await g
async def start(self) -> dict: """ 开始上传 Returns: dict: 返回带有 bvid 和 aid 的字典。 """ task = create_task(self._main()) self.__task = task try: result = await task self.__task = None return result except CancelledError: # 忽略 task 取消异常 pass except Exception as e: raise e
async def select(*cs: Chan[Any]) -> AsyncIterator[Tuple[Chan[Any], Any]]: """ async for ch, item in select(ch1, ch2, ch3, ...): if ch == ch1: ... elif ch == ch2: ... elif ch == ch3: ... """ chans: MutableSequence[Chan[Any]] = [*cs] while chans: _ready, _, _ = await race(*(create_task(c._on_recvable()) for c in chans)) ready = _ready.result() if not ready: chans[:] = (c for c in chans if c) elif ready.recvable(): yield ready, ready.try_recv()
async def handle_done_report(msg: Message, state: FSMContext): response = await state.get_data() await state.finish() await redirect_to_main_menu('Succesfully sent') create_task(send_response_to_user(response))
async def no_language_exception_handler(update: Update, e: NoLanguageException): await redirect_to_request_language() create_task(track_user()) return True
def listen(self, channel): logger.info(f"Registering channel {channel}.") self.channels[channel] = self._create_channel(channel) self.listener_tasks[channel] = create_task(self._listen_to(channel)) logger.info(f"Registered channel {channel}.")
def delayed_send(ch: Chan[int], n: int, delay: float) -> None: async def cont() -> None: await sleep(delay) await (ch << n) create_task(cont())
async def test_1(self) -> None: create_task(echo(self.ask, reply=self.reply, cycles=BIG_REP_FACTOR)) with self.subTest(): for i in range(BIG_REP_FACTOR): ans = await self.req(i) self.assertEqual(ans, i)