async def finish(self, exc_typ=None, exc=None, tb=None): self.final_future.cancel() if hasattr(self, "_task"): await asyncio.wait([self._task]) if hasattr(self.server.finder.finish, "mock_calls"): assert len(self.server.finder.finish.mock_calls) == 0 waited = [] async with hp.TaskHolder(hp.create_future()) as ts: for cleaner in self.cleaners: waited.append(ts.add(cleaner())) async with hp.TaskHolder(hp.create_future()) as ts: if hasattr(self, "Wrapped"): waited.append(ts.add(self.Wrapped.__aexit__(exc_typ, exc, tb))) waited.append(ts.add(pytest.helpers.wait_for_no_port(self.port))) if hasattr(self, "ws"): waited.append(ts.add(self.ws.__aexit__(None, None, None))) await self.ts.finish() # make sure none failed for w in waited: await w # Prevent coroutine not awaited error await asyncio.sleep(0.01) if hasattr(self.server.finder.finish, "mock_calls"): self.server.finder.finish.assert_called_once_with()
def __init__( self, sender, *, limit=30, finder=None, forget_after=30, final_future=None, search_interval=20, time_between_queries=None, ): self.sender = sender self.search_interval = search_interval self.time_between_queries = time_between_queries final_future = final_future or sender.stop_fut self.final_future = hp.ChildOfFuture( final_future, name="DeviceFinderDaemon::__init__[final_future]" ) self.own_finder = not bool(finder) self.finder = finder or Finder( self.sender, self.final_future, forget_after=forget_after, limit=limit ) self.ts = hp.TaskHolder(self.final_future, name="DeviceFinderDaemon::__init__[ts]") self.hp_tick = hp.tick
async def finish(self): self.final_future.cancel() async with hp.TaskHolder(asyncio.Future()) as ts: for serial, device in sorted(self.devices.items()): ts.add(device.finish()) del self.devices[serial]
async def run(self): cannon = self.make_cannon() self.started = time.time() animations = self.run_options.animations_iter self.combined_state = State(self.final_future) async with self.reinstate(), hp.TaskHolder( self.final_future, name="AnimationRunner::run[task_holder]") as ts: self.transfer_error( ts, ts.add( self.animate(ts, cannon, self.combined_state, animations))) async for collected in self.collect_parts(ts): try: if self.run_options.combined: await self.combined_state.add_collected(collected) else: state = State(self.final_future) await state.add_collected(collected) self.transfer_error( ts, ts.add(self.animate(ts, cannon, state, animations))) except asyncio.CancelledError: raise except Finish: pass except Exception as error: log.exception(hp.lc("Failed to add device", error=error))
async def call_finishers(): async with hp.TaskHolder( self.final_future, name=f"DeviceSession({self.device.serial})::finish[ts]" ) as ts: for io in self.managed: made.append(ts.add(io.finish_session(), silent=True)) self.managed = []
async def finish(self, exc_typ=None, exc=None, tb=None): self.final_future.cancel() async with hp.TaskHolder( hp.create_future(name="Finder::finish[task_holder_final_future]"), name="Finder::finish[task_holder]", ) as ts: for serial, device in sorted(self.devices.items()): ts.add(device.finish(exc_typ, exc, tb)) del self.devices[serial]
async def start(self): await self.device.prepare() self.parent_ts = hp.TaskHolder( self.final_future, name=f"DeviceSession({self.device.serial})::start[parent]" ) await self.parent_ts.start() made = [] async with hp.TaskHolder( self.final_future, name=f"DeviceSession({self.device.serial})::start[ts]" ) as ts: for _, io in self.device.io.items(): self.managed.append(io) made.append( ts.add(io.start_session(self.final_future, self.parent_ts), silent=True) ) # Raise any exceptions for t in made: await t await self.device.reset()
async def action(self, method, verb, identities): if not identities: identities = list(self.animations) changed = [] async with hp.TaskHolder( self.final_future, name=f"Animations::action({method})[ts]") as ts: for identity in identities: if identity in self.animations: changed.append(identity) ts.add(getattr(self.animations[identity], method)()) return self.info(**{verb: changed})
def __init__(self, target): self.transport_target = target self.found = Found() self.stop_fut = hp.ChildOfFuture( self.transport_target.final_future, name=f"{type(self).__name__}.__init__|stop_fut|") self.receiver = Receiver() self.received_data_tasks = hp.TaskHolder( self.stop_fut, name=f"{type(self).__name__}.__init__|received_data_tasks|") self.make_plans = __import__( "photons_control.planner").planner.make_plans self.setup()
async def for_test(self, final_future, udp=False): async with hp.TaskHolder(final_future, name="DeviceCollection::for_test") as ts: sessions = [ device.session(final_future) for device in self.devices.values() ] try: tt = [] for session in sessions: tt.append(ts.add(session.start())) await hp.wait_for_all_futures( *tt, name="DeviceCollection::for_test[wait_for_start]") configuration = { "final_future": final_future, "protocol_register": protocol_register, "devices": [device for device in self.devices.values()], } if udp: target = LanTarget.create(configuration) else: target = MemoryTarget.create(configuration) async with target.session() as sender: if udp: for device in self.devices.values(): await sender.add_service( device.serial, Services.UDP, port=device.io["UDP"].options.port, host="127.0.0.1", ) for store in self.stores.values(): store.clear() yield sender finally: exc_typ, exc, tb = sys.exc_info() for session in sessions: ts.add(session.finish(exc_typ=exc_typ, exc=exc, tb=tb))
async def start_session(self, final_future, parent_ts): self.last_final_future = final_future self.parent_ts = parent_ts self.final_future = hp.ChildOfFuture( final_future, name= f"{self.__class__.__name__}({self.device.serial}::start_session[final_future]", ) self.ts = hp.TaskHolder( self.final_future, name= f"{self.__class__.__name__}({self.device.serial}::start_session[ts]", ) self.incoming = hp.Queue( self.final_future, name= f"{self.__class__.__name__}({self.device.serial}::start_session[incoming]", ) await self.ts.start() self.ts.add(self.incoming_loop())
wait = hp.create_future() queue = hp.Queue(final_future) ff = hp.create_future() found = [] async def fill(): for i in (2, 3, 4): queue.append(i) await wait for i in (5, 6, 7): queue.append(i) try: async with hp.TaskHolder(ff) as ts: ts.add(fill()) queue.append(1) async for item in queue: if item == 5: final_future.cancel() found.append(item) if item == 4: wait.set_result(True) finally: ff.cancel()
async def doit(): async with hp.TaskHolder(final_future) as t: t.add(a_task("one")) t.add(a_task("two")) waiter.set_result(True) await hp.create_future()
def ts(self): return hp.TaskHolder(self.final_future)
async with hp.tick(*self.args, **self.kwargs) as ticks: async for i, nxt_time in ticks: if i == 4: wait.set_result(True) yield i, nxt_time p3 = mock.patch.object(V.daemon.finder, "find", find) p4 = mock.patch.object(V.daemon, "hp_tick", Tick) with p1, p2, p3, p4: async def run(): async with V.daemon: await hp.create_future() async with hp.TaskHolder(V.final_future) as ts: t = ts.add(run()) await wait t.cancel() for eril in (d1ril, d2ril): assert len(eril.mock_calls) >= 3 assert eril.mock_calls[0] == mock.call( V.daemon.sender, V.daemon.time_between_queries, V.daemon.finder.collections ) async it "keeps going if find fails", V: called = [] async with pytest.helpers.FutureDominoes(expected=5) as futs:
log.error.assert_called_once_with( "a different message", exc_info=(ValueError, error, mock.ANY) ) log.error.reset_mock() with assertRaises(TypeError, "wat"): with hp.just_log_exceptions(log, message="a different message", reraise=[TypeError]): raise TypeError("wat") log.assert_not_called() describe "TaskHolder": it "takes in a final future": final_future = asyncio.Future() holder = hp.TaskHolder(final_future) assert holder.ts == [] assert holder.final_future is final_future async it "can take in tasks": called = [] async def wait(amount): try: await asyncio.sleep(amount) finally: called.append(amount) final_future = asyncio.Future() async with hp.TaskHolder(final_future) as ts: ts.add(wait(0.05))
LightMessages.GetColor(), LightMessages.GetColor(), LightMessages.GetColor(), DeviceMessages.GetHostFirmware(), keep_duplicates=True, ) ff.cancel() checker_task = None time_between_queries = {"FIRMWARE": 100} await FoundSerials().find(V.sender, timeout=1) with hp.ChildOfFuture(V.final_future) as ff: async with hp.TaskHolder(ff, name="TEST") as ts: checker_task = ts.add(checker(ff)) ts.add( V.device.refresh_information_loop( V.sender, time_between_queries, V.finder.collections ) ) await checker_task async it "can start an information loop for a switch", fake_time, sender, finder, final_future: V = VBase(fake_time, sender, finder, final_future) await V.choose_device("switch") fake_time.set(1) msgs = [e.value.msg for e in list(InfoPoints) if e is not InfoPoints.LIGHT_STATE]
) assert V.t.time <= 76 await asyncio.wait([Futs.firmware]) # First firmware was at t=2 # So next refresh after 102 # So needs a full cycle after that assert V.t.time >= 107 V.received( LightMessages.GetColor(), LightMessages.GetColor(), DeviceMessages.GetHostFirmware(), keep_duplicates=True, ) checker_task = None time_between_queries = {"FIRMWARE": 100} with mock.patch.object(hp, "tick", tick): async with hp.TaskHolder(V.runner.final_future) as ts: checker_task = ts.add(checker()) ts.add_task( V.device.ensure_refresh_information_loop( V.runner.sender, time_between_queries, V.finder.collections ) ) await checker_task await futs
async def parent_ts(final_future): async with hp.TaskHolder(final_future) as ts: yield ts