예제 #1
0
    async def find(self, fltr):
        _, removed = await self._ensure_devices(fltr)

        def error(e):
            log.error(
                hp.lc(
                    "Failed to determine if device matched filter",
                    error=e,
                    error_type=type(e).__name__,
                ))

        streamer = hp.ResultStreamer(self.final_future,
                                     error_catcher=error,
                                     exceptions_only_to_error_catcher=True)

        for device in removed:
            await streamer.add_coroutine(device.finish())

        for serial, device in list(self.devices.items()):
            if fltr.matches_all:
                fut = asyncio.Future()
                fut.set_result(True)
                await streamer.add_task(fut, context=device)
            else:
                await streamer.add_coroutine(device.matches(
                    self.sender, fltr, self.collections),
                                             context=device)

        streamer.no_more_work()

        async with streamer:
            async for result in streamer:
                if result.successful and result.value and result.context:
                    yield result.context
예제 #2
0
    async def info(self, fltr):
        def error(e):
            log.error(
                hp.lc("Failed to find information for device",
                      error=e,
                      error_type=type(e).__name__))

        streamer = hp.ResultStreamer(self.final_future,
                                     error_catcher=error,
                                     exceptions_only_to_error_catcher=True)

        async def find():
            async for device in self.find(fltr):
                await streamer.add_coroutine(
                    device.matches(
                        self.sender,
                        Filter.empty(refresh_info=fltr.refresh_info),
                        self.collections),
                    context=device,
                )

        await streamer.add_coroutine(find(), context=True)
        streamer.no_more_work()

        async with streamer:
            async for result in streamer:
                if result.context is True and not result.successful:
                    raise result.value
                if result.successful and result.value and result.context:
                    yield result.context
예제 #3
0
    async def stream(self, animation_state):
        self.started = time.time()
        del self.ticker

        async def tick():
            async with self.ticker as ticks:
                async for result in ticks:
                    yield result

        def errors(e):
            if not isinstance(e, asyncio.CancelledError):
                log.error(hp.lc(error=e, error_type=type(e)))

        with hp.ChildOfFuture(
                self.final_future,
                name="Animation::streamer[stop_fut]") as stop_fut:
            async with hp.ResultStreamer(
                    stop_fut,
                    error_catcher=errors,
                    exceptions_only_to_error_catcher=True,
                    name=f"Animation({self.__class__.__name__})",
            ) as streamer:
                await streamer.add_generator(tick(),
                                             context=AnimationEvent.Types.TICK)
                await streamer.add_generator(
                    self.make_user_events(animation_state),
                    context=AnimationEvent.Types.USER_EVENT)
                streamer.no_more_work()

                async for result in streamer:
                    if result.value is hp.ResultStreamer.GeneratorComplete:
                        continue
                    yield result
예제 #4
0
    async def info(self, fltr):
        catcher = partial(log_errors, "Failed to find information for device")

        async def find():
            async for device in self.find(fltr):
                await streamer.add_coroutine(
                    device.matches(
                        self.sender, Filter.empty(refresh_info=fltr.refresh_info), self.collections
                    ),
                    context=device,
                )

        streamer = hp.ResultStreamer(
            self.final_future, error_catcher=catcher, name="Finder::info[streamer]"
        )

        async with streamer:
            await streamer.add_coroutine(find(), context=True)
            streamer.no_more_work()

            async for result in streamer:
                if not result.successful:
                    if result.context is True:
                        try:
                            raise result.value
                        finally:
                            del result

                elif result.value and result.context:
                    yield result.context
예제 #5
0
파일: script.py 프로젝트: delfick/photons
        async def retrieve_all(self, msg, complete):
            try:
                async with hp.ResultStreamer(
                        self.stop_fut,
                        name="FromGenerator>Runner::retrieve_all[streamer]",
                        error_catcher=squash,
                ) as streamer:
                    for item in self.item.simplifier(msg):
                        await streamer.add_generator(self.retrieve(item),
                                                     context="retrieve")
                    streamer.no_more_work()

                    async for result in streamer:
                        if result.value is hp.ResultStreamer.GeneratorComplete:
                            continue

                        if not result.successful:
                            if not isinstance(result.value, self.Unsuccessful):
                                hp.add_error(self.error_catcher, result.value)
                            if not complete.done():
                                complete.set_result(False)
                        else:
                            yield result.value
            finally:
                if not complete.done():
                    exc_info = sys.exc_info()
                    if exc_info[0] is None:
                        complete.set_result(True)
                    else:
                        complete.set_result(False)
예제 #6
0
            async def make_streamer(**kwargs):
                streamer = None
                final_future = hp.create_future()

                try:
                    streamer = hp.ResultStreamer(final_future, **kwargs)
                    yield streamer
                finally:
                    final_future.cancel()
                    if streamer:
                        await streamer.finish()
예제 #7
0
파일: script.py 프로젝트: delfick/photons
        def __init__(self, item, stop_fut, reference, sender, kwargs):
            self.item = item
            self.kwargs = kwargs
            self.reference = reference
            self.sender = sender

            self.stop_fut = hp.ChildOfFuture(
                stop_fut, name="FromGenerator>Runner::__init__[stop_fut]")

            self.streamer = hp.ResultStreamer(
                self.stop_fut,
                name="FromGenerator>Runner::__init__[streamer]",
                error_catcher=squash,
            )
예제 #8
0
    async def find(self, fltr):
        if self.final_future.done():
            return

        refresh = False if fltr is None else fltr.refresh_discovery

        try:
            serials = await self._find_all_serials(refresh=refresh)
        except asyncio.CancelledError:
            raise
        except Exception:
            log.exception("Failed to find serials")
            serials = []

        removed = self._ensure_devices(serials)

        catcher = partial(log_errors, "Failed to determine if device matched filter")

        async with hp.ResultStreamer(
            self.final_future, name="Finder::find[streamer]", error_catcher=catcher
        ) as streamer:
            for device in removed:
                await streamer.add_coroutine(device.finish())

            for serial, device in list(self.devices.items()):
                if fltr.matches_all:
                    fut = hp.create_future(name=f"Finder({serial})::find[fut]")
                    fut.set_result(True)
                    await streamer.add_task(fut, context=device)
                else:
                    await streamer.add_coroutine(
                        device.matches(self.sender, fltr, self.collections), context=device
                    )

            streamer.no_more_work()

            async with streamer:
                async for result in streamer:
                    if result.successful and result.value and result.context:
                        yield result.context
예제 #9
0
    async def write_messages(self, sender, packets, kwargs):
        """Send all our packets and collect all the results"""

        error_catcher = kwargs["error_catcher"]

        async with hp.ResultStreamer(
                sender.stop_fut,
                error_catcher=silence_errors,
                name="Item::write_messages[streamer]") as streamer:
            count = 0
            for original, packet in packets:
                count += 1
                await streamer.add_coroutine(self.do_send(
                    sender, original, packet, kwargs),
                                             context=packet)

            streamer.no_more_work()

            got = 0
            async for result in streamer:
                got += 1
                if result.successful:
                    for msg in result.value:
                        yield msg
                else:
                    exc = result.value
                    pkt = result.context
                    if isinstance(exc, asyncio.CancelledError):
                        hp.add_error(
                            error_catcher,
                            TimedOut(
                                "Message was cancelled",
                                sent_pkt_type=pkt.pkt_type,
                                serial=pkt.serial,
                                source=pkt.source,
                                sequence=pkt.sequence,
                            ),
                        )
                    else:
                        hp.add_error(error_catcher, exc)
예제 #10
0
파일: gatherer.py 프로젝트: delfick/photons
    async def gather(self, plans, reference, error_catcher=None, **kwargs):
        """
        This is an async generator that yields tuples of
        ``(serial, label, info)`` where ``serial`` is the serial of the device,
        ``label`` is the label of the plan, and ``info`` is the result of
        executing that plan.

        The error handling of this function is the same as the async generator
        behaviour in :ref:`sender <sender_interface>` API.
        """
        if not plans:
            return

        with catch_errors(error_catcher) as error_catcher:
            kwargs["error_catcher"] = error_catcher

            serials, missing = await find_serials(reference,
                                                  self.sender,
                                                  timeout=kwargs.get(
                                                      "find_timeout", 20))

            for serial in missing:
                hp.add_error(error_catcher, FailedToFindDevice(serial=serial))

            async with hp.ResultStreamer(
                    self.sender.stop_fut,
                    error_catcher=error_catcher,
                    exceptions_only_to_error_catcher=True,
            ) as streamer:
                for serial in serials:
                    await streamer.add_generator(
                        self._follow(plans, serial, **kwargs))
                streamer.no_more_work()

                async for result in streamer:
                    if result.successful:
                        yield result.value
예제 #11
0
    async def search_loop(self):
        refreshing = hp.ResettableFuture(name="DeviceFinderDaemon::search_loop[refreshing]")
        refresh_discovery_fltr = Filter.empty(refresh_discovery=True)

        async def add(streamer):
            if refreshing.done():
                return

            refreshing.set_result(True)

            async for device in self.finder.find(refresh_discovery_fltr):
                await streamer.add_coroutine(
                    device.refresh_information_loop(
                        self.sender, self.time_between_queries, self.finder.collections
                    ),
                    context=device,
                )

        async def ticks():
            async with self.hp_tick(self.search_interval, final_future=self.final_future) as ticks:
                async for info in ticks:
                    yield info

        catcher = partial(log_errors, "Something went wrong in a search")

        async with hp.ResultStreamer(
            self.final_future,
            name="DeviceFinderDaemon::search_loop[streamer]",
            error_catcher=catcher,
        ) as streamer:
            await streamer.add_generator(ticks(), context="finder_tick")
            streamer.no_more_work()

            async for result in streamer:
                if result.successful and result.context == "finder_tick":
                    refreshing.reset()
                    await streamer.add_coroutine(add(streamer))
예제 #12
0
파일: base.py 프로젝트: delfick/photons
    async def send_single(self,
                          original,
                          packet,
                          *,
                          timeout,
                          no_retry=False,
                          broadcast=False,
                          connect_timeout=10):

        transport, is_broadcast = await self._transport_for_send(
            None, packet, original, broadcast, connect_timeout)

        retry_gaps = self.retry_gaps(original, transport)

        writer = Writer(
            self,
            transport,
            self.receiver,
            original,
            packet,
            retry_gaps,
            did_broadcast=is_broadcast,
            connect_timeout=connect_timeout,
        )

        results = []

        unlimited = False
        if hasattr(original, "Meta"):
            unlimited = original.Meta.multi == -1

        async def wait_for_remainders(tick_fut, streamer_fut):
            try:
                await hp.wait_for_all_futures(tick_fut)
            finally:
                if unlimited and any(result.wait_for_result()
                                     for result in results):
                    await hp.wait_for_first_future(*results)
                streamer_fut.cancel()

        tick_fut = hp.ChildOfFuture(
            self.stop_fut,
            name=
            f"SendPacket({original.pkt_type, packet.serial})::send_single[tick_fut]",
        )
        streamer_fut = hp.ChildOfFuture(
            self.stop_fut,
            name=
            f"SendPacket({original.pkt_type, packet.serial})::send_single[streamer_fut]",
        )

        retry_ticker = retry_gaps.retry_ticker(
            name=
            f"{type(self).__name__}({type(transport).__name__})::retry_ticker")

        with tick_fut, streamer_fut:
            async with hp.ResultStreamer(
                    streamer_fut,
                    name=
                    f"SendPacket({original.pkt_type, packet.serial}).send_single"
            ) as streamer:
                await streamer.add_generator(
                    retry_ticker.tick(tick_fut, timeout),
                    context="tick",
                    on_done=lambda res: tick_fut.cancel(),
                )
                await streamer.add_coroutine(
                    wait_for_remainders(tick_fut, streamer_fut))
                streamer.no_more_work()

                async for result in streamer:
                    if not result.successful:
                        try:
                            raise result.value
                        finally:
                            del result

                    if result.context == "tick":
                        if not no_retry or not results:
                            result = await writer()
                            results.append(result)
                            await streamer.add_task(result, context="write")
                    elif result.context == "write":
                        return result.value

        raise TimedOut(
            "Waiting for reply to a packet",
            serial=packet.serial,
            sent_pkt_type=packet.pkt_type,
            source=packet.source,
            sequence=packet.sequence,
        )
예제 #13
0
 def streamer(s):
     return hp.ResultStreamer(s.final_future, error_catcher=s.error_catcher)
예제 #14
0
            async def gen(reference, sender, **kwargs):
                with alter_called("primary"):
                    async with hp.tick(0.3) as ticks:
                        async for i, _ in ticks:
                            called.append(("primary", i))
                            yield make_secondary_msg(i, m)

            return FromGenerator(gen, reference_override=True)

        msg = make_primary_msg(m)

        await FoundSerials().find(sender, timeout=1)
        sender.received.clear()

        fut = hp.create_future()
        async with hp.ResultStreamer(fut) as streamer:

            async def pkts():
                with alter_called("pkts"):
                    async for pkt in sender(msg, light1.serial):
                        yield pkt

            t = await streamer.add_generator(pkts(), context="pkt")
            streamer.no_more_work()

            found = []
            async for result in streamer:
                if result.context == "pkt":
                    found.append(result)
                    if len(found) == 18:
                        t.cancel()
예제 #15
0
        self.other = other
        return isinstance(other, asyncio.CancelledError)

    def __repr__(self):
        return f"<C: {getattr(self, 'other', None)}"


describe "ResultStreamer":
    it "takes in final_future and other options":
        final_future = asyncio.Future()
        error_catcher = mock.Mock(name="error_catcher")
        exceptions_only_to_error_catcher = mock.Mock(name="exceptions_only_to_error_catcher")

        streamer = hp.ResultStreamer(
            final_future,
            error_catcher=error_catcher,
            exceptions_only_to_error_catcher=exceptions_only_to_error_catcher,
        )

        assert not streamer.final_future.done()
        assert streamer.error_catcher is error_catcher
        assert streamer.exceptions_only_to_error_catcher is exceptions_only_to_error_catcher

        assert streamer.ts == []
        assert isinstance(streamer.queue, asyncio.Queue)
        assert not streamer.stop_on_completion

    async it "has a final future as a child of that passed in":
        final_future = asyncio.Future()
        streamer = hp.ResultStreamer(final_future)
        streamer.final_future.cancel()
예제 #16
0
 def streamer(s):
     return hp.ResultStreamer(s.final_future)
예제 #17
0
        self.other = other
        return isinstance(other, asyncio.CancelledError)

    def __repr__(self):
        return f"<C: {getattr(self, 'other', None)}"


describe "ResultStreamer":
    it "takes in final_future and other options":
        final_future = hp.create_future()
        error_catcher = mock.Mock(name="error_catcher")
        exceptions_only_to_error_catcher = mock.Mock(name="exceptions_only_to_error_catcher")

        streamer = hp.ResultStreamer(
            final_future,
            error_catcher=error_catcher,
            exceptions_only_to_error_catcher=exceptions_only_to_error_catcher,
        )

        assert not streamer.final_future.done()
        assert streamer.error_catcher is error_catcher
        assert streamer.exceptions_only_to_error_catcher is exceptions_only_to_error_catcher

        assert len(streamer.ts.ts) == 0
        assert isinstance(streamer.queue, hp.Queue)
        assert not streamer.stop_on_completion

    async it "has a final future as a child of that passed in":
        final_future = hp.create_future()
        streamer = hp.ResultStreamer(final_future)
        streamer.final_future.cancel()
예제 #18
0
 async def __aenter__(s):
     s.streamer = hp.ResultStreamer(s.final_future, **s.kwargs)
     return s.streamer
예제 #19
0
                assert (await searcher.discover()) is serials

            assert searcher.search_fut.result() is serials

        async it "does not do a search if one is already in progress", searcher:
            called = []
            serials = mock.Mock(name="serials")
            continue_event = asyncio.Future()

            async def _serials():
                called.append("get_serials")
                await continue_event
                assert not searcher.search_fut.done()
                return serials

            streamer = hp.ResultStreamer(asyncio.Future())
            await streamer.add_coroutine(searcher.discover())
            await streamer.add_coroutine(searcher.discover())
            streamer.no_more_work()
            asyncio.get_event_loop().call_soon(continue_event.set_result, True)

            with mock.patch.object(searcher, "_serials", _serials):
                async with streamer:
                    async for result in streamer:
                        assert result.value is serials

            assert called == ["get_serials"]

        async it "does not search at all if the search_fut is already resolved", searcher:
            serials = mock.Mock(name="serials")
            searcher.search_fut.reset()