Beispiel #1
0
    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()
Beispiel #2
0
    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
Beispiel #3
0
    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]
Beispiel #4
0
    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))
Beispiel #5
0
 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 = []
Beispiel #6
0
    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]
Beispiel #7
0
    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()
Beispiel #8
0
    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})
Beispiel #9
0
    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()
Beispiel #10
0
    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))
Beispiel #11
0
    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())
Beispiel #12
0
            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()
Beispiel #13
0
 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()
Beispiel #14
0
 def ts(self):
     return hp.TaskHolder(self.final_future)
Beispiel #15
0
                        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:
Beispiel #16
0
        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
Beispiel #19
0
async def parent_ts(final_future):
    async with hp.TaskHolder(final_future) as ts:
        yield ts