Esempio n. 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()
Esempio n. 2
0
        class V:
            fut1 = hp.create_future()
            fut2 = hp.create_future()
            fut3 = hp.create_future()
            fut4 = hp.create_future()
            final_fut = hp.create_future()

            @hp.memoized_property
            def available_futs(s):
                return [s.fut1, s.fut2, s.fut3, s.fut4]
Esempio n. 3
0
            async def execute_task(self, collector, **kwargs):
                called.append(1)

                async def cleanup1():
                    called.append("c1a")
                    fut = hp.create_future()
                    fut.set_result(True)
                    await fut
                    called.append("c1b")

                async def cleanup2():
                    called.append("c2a")
                    fut = hp.create_future()
                    fut.set_result(True)
                    await fut
                    called.append("c2b")

                collector.photons_app.cleaners.extend([cleanup1, cleanup2])
                called.append(2)

                try:
                    hp.get_event_loop().call_later(0.02, collector.photons_app.final_future.cancel)
                    await asyncio.sleep(10)
                    called.append("unexpected")
                except:
                    fut = hp.create_future()
                    fut.set_result(True)
                    await fut
                    called.append(3)
                    raise
                finally:
                    called.append(4)
Esempio n. 4
0
            async def execute_task(self, collector, **kwargs):
                called.append(1)

                async def cleanup1():
                    called.append("c1a")
                    fut = hp.create_future()
                    fut.set_result(True)
                    await fut
                    called.append("c1b")

                async def cleanup2():
                    called.append("c2a")
                    fut = hp.create_future()
                    fut.set_result(True)
                    await fut
                    called.append("c2b")

                collector.photons_app.cleaners.extend([cleanup1, cleanup2])
                called.append(2)
                try:
                    raise PhotonsAppError("YO")
                except:
                    fut = hp.create_future()
                    fut.set_result(True)
                    await fut
                    called.append(3)
                    raise
                finally:
                    called.append(4)
Esempio n. 5
0
        class V:
            final_future = hp.create_future()
            default_broadcast = "1.2.3.255"

            @hp.memoized_property
            def transport_target(s):
                transport_target = mock.Mock(
                    name="target",
                    spec=[
                        "script",
                        "final_future",
                        "default_broadcast",
                        "discovery_options",
                        "gaps",
                    ],
                )
                transport_target.gaps = s.gaps
                transport_target.final_future = s.final_future
                transport_target.default_broadcast = s.default_broadcast
                transport_target.discovery_options = (
                    NoDiscoveryOptions.FieldSpec().empty_normalise()
                )
                return transport_target

            @hp.memoized_property
            def session(s):
                return NetworkSession(s.transport_target)

            @hp.memoized_property
            def gaps(s):
                return Gaps(
                    gap_between_ack_and_res=0.2, gap_between_results=0.35, timeouts=[(1, 1)]
                )
Esempio n. 6
0
    def wait_for_event(self, want):
        fut = hp.create_future(name=f"EventWaiter::wait_for_event[{repr(want)}]")

        def match(event):
            return event | want

        self.waiters.append((fut, match))
        return fut
Esempio n. 7
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]
Esempio n. 8
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()
Esempio n. 9
0
 async def execute_task(self, notify, output, **kwargs):
     try:
         fut = hp.create_future()
         fut.cancel()
         notify()
         await fut
     except asyncio.CancelledError:
         with open(output, "w") as fle:
             fle.write("CANCELLED")
         raise
     finally:
         with open(output, "a") as fle:
             fle.write(str(sys.exc_info()[0]))
Esempio n. 10
0
        async def retrieve(self, streamer):
            streamer.no_more_work()

            started = hp.create_future()

            async def retrieve():
                results = []
                started.set_result(True)
                async for result in streamer:
                    results.append(result)
                return results

            return started, hp.async_as_background(retrieve())
Esempio n. 11
0
    def wait_for_incoming(self, io, pkt):
        if isinstance(pkt, type):
            desc = pkt.__name__
        elif isinstance(pkt, tuple):
            desc = f"{pkt[0].__name__}({pkt[1]})"
        else:
            desc = "{pkt.__class__.__name__}({repr(pkt.payload)})"

        fut = hp.create_future(name=f"EventWaiter::wait_incoming[{io}, {desc}]")

        def match(event):
            return event == Events.INCOMING(self.device, io, pkt=pkt)

        self.waiters.append((fut, match))
        return fut
Esempio n. 12
0
    class V:
        final_future = hp.create_future()

        @hp.memoized_property
        def transport_target(s):
            return mock.Mock(
                name="transport_target",
                final_future=s.final_future,
                protocol_register=protocol_register,
                spec=["final_future", "protocol_register"],
            )

        @hp.memoized_property
        def communication(s):
            return Communication(s.transport_target)
Esempio n. 13
0
    async def separate_final_future(self, sleep=0):
        other_future = hp.create_future(
            name="PhotonsApp::separate_final_future")

        def stop():
            hp.get_event_loop().call_soon_threadsafe(other_future.cancel)

        self.loop.remove_signal_handler(signal.SIGTERM)
        self.loop.add_signal_handler(signal.SIGTERM, stop)

        try:
            yield other_future
        finally:
            if sleep > 0:
                await asyncio.sleep(sleep)
            self.final_future.cancel()
Esempio n. 14
0
            class V:
                final_future = hp.create_future()
                error_catcher = mock.Mock(name="error_catcher")

                @hp.memoized_property
                def streamer(s):
                    return hp.ResultStreamer(s.final_future, error_catcher=s.error_catcher)

                async def retrieve(s):
                    results = []

                    s.streamer.no_more_work()
                    async for result in s.streamer:
                        results.append(result)

                    return results
Esempio n. 15
0
        def resolve(self):
            def make_animation(final_future, pauser=None):
                options = self.animator.Options.FieldSpec().normalise(Meta.empty(), self.options)
                animation = self.animator.Animation(final_future, options, pauser=pauser)
                if self.options is not sb.NotSpecified:
                    for attr in animation.overridable:
                        if attr in self.options:
                            setattr(animation, attr, self.options[attr])
                return animation

            # Make sure the options can be resolved
            fut = hp.create_future(name="Animator>Resolver::resolve[fut]")
            fut.cancel()
            make_animation(fut)

            return make_animation, self.background
Esempio n. 16
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
Esempio n. 17
0
async def run_prompt(daemon, final_future, loop):
    readline.parse_and_bind("")

    def get_command(done):
        try:
            nxt = input()
        except Exception as error:
            if isinstance(error, (EOFError, KeyboardInterrupt)):
                error = UserQuit()
            if not final_future.done():
                final_future.set_exception(error)

        if final_future.done():
            return

        loop.call_soon_threadsafe(done.set_result, nxt.strip())

    while True:
        write_prompt()

        done = hp.create_future(name="||run_prompt[done]")

        thread = threading.Thread(target=get_command, args=(done, ))
        thread.daemon = True
        thread.start()

        nxt = await done

        if nxt:
            try:
                await process_command(daemon, nxt)
            except asyncio.CancelledError:
                raise
            except:
                log.exception("Unexpected error")

        if final_future.done():
            return
Esempio n. 18
0
        async def consume(self, gen, streamer):
            complete = None

            try:
                while True:
                    try:
                        msg = await gen.asend(complete)
                        if isinstance(msg, Exception):
                            hp.add_error(self.error_catcher, msg)
                            continue

                        if self.stop_fut.done():
                            break

                        complete = hp.create_future(
                            name="FromGenerator>Runner::getter[complete]")
                        await streamer.add_generator(self.retrieve_all(
                            msg, complete),
                                                     context=self.Value)
                    except StopAsyncIteration:
                        break
            finally:
                exc_info = sys.exc_info()
                if exc_info[0] not in (None, asyncio.CancelledError):
                    hp.add_error(self.error_catcher, exc_info[1])

                await streamer.add_coroutine(
                    hp.stop_async_generator(
                        gen,
                        complete,
                        name="FromGenerator>Runner::consume[finally_stop_gen]",
                        exc=exc_info[1],
                    ),
                    force=True,
                )

                if exc_info[0] is not asyncio.CancelledError:
                    return False
Esempio n. 19
0
    async def spawn(self, packet, *, timeout=10, create=True):
        if self.transport is not None:
            if self.transport.done() and (self.transport.cancelled()
                                          or self.transport.exception()):
                self.transport = None

        if self.transport is not None and self.transport.done():
            if not await self.is_transport_active(packet,
                                                  self.transport.result()):
                self.transport = None

        if not create and (self.transport is None
                           or not self.transport.done()):
            return None

        if self.transport is None:
            self.transport = hp.create_future(
                name=
                f"Transport::{self.session.__class__.__name__}::spawn[transport]"
            )
            t = hp.async_as_background(self.spawn_transport(timeout))
            t.add_done_callback(hp.transfer_result(self.transport))

        return await self.transport
Esempio n. 20
0
                async def execute_task(s, **kwargs):
                    fut = hp.create_future()
                    got.append((time.time(), "first"))

                    async def wait():
                        try:
                            got.append((time.time(), "wait"))
                            await fut
                        except asyncio.CancelledError:
                            got.append((time.time(), "wait stopped"))

                    s.task_holder.add(wait())

                    async def sleeper():
                        await asyncio.sleep(2)
                        got.append((time.time(), "blink"))
                        await asyncio.sleep(8)
                        got.append((time.time(), "rested"))

                    s.task_holder.add(sleeper())

                    async def cleaner1():
                        got.append((time.time(), "cleaner1"))

                    s.photons_app.cleaners.append(cleaner1)

                    async def cleaner2():
                        await asyncio.sleep(1)
                        got.append((time.time(), "cleaner2"))

                    s.photons_app.cleaners.append(cleaner2)

                    await asyncio.sleep(3)
                    got.append((time.time(), "wait now"))

                    s.photons_app.loop.call_later(0.5, fut.cancel)
Esempio n. 21
0
            class V:
                final_future = hp.create_future()

                @hp.memoized_property
                def streamer(s):
                    return hp.ResultStreamer(s.final_future)
Esempio n. 22
0
        def make_primary_msg(m):
            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:
Esempio n. 23
0
 def final_future(self):
     fut = hp.create_future()
     try:
         yield fut
     finally:
         fut.cancel()
Esempio n. 24
0
def final_future():
    final_future = hp.create_future()
    try:
        yield final_future
    finally:
        final_future.cancel()
Esempio n. 25
0
def final_future():
    ff = hp.create_future()
    try:
        yield ff
    finally:
        ff.cancel()
Esempio n. 26
0
import pytest
import sys


class C:
    def __eq__(self, other):
        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)
Esempio n. 27
0
import pytest
import uuid
import time


@pytest.fixture()
def loop():
    return hp.get_event_loop()


describe "creating a future":
    it "can create a future from a provided loop":
        fut = mock.Mock(name="future")
        loop = mock.Mock(name="loop")
        loop.create_future.return_value = fut
        assert hp.create_future(loop=loop) is fut
        assert fut.name is None
        loop.create_future.assert_called_once_with()

    it "can create a future from current loop":
        fut = hp.create_future()
        assert isinstance(fut, asyncio.Future)
        assert fut.name is None

    it "can give a name to the future":
        fut = hp.create_future(name="hi")
        assert fut.name == "hi"


describe "fut_has_callback":
    async it "says no if fut has no callbacks":
Esempio n. 28
0
# coding: spec

from photons_control.device_finder import DeviceFinderDaemon, Finder, Filter, DeviceFinder, Device

from photons_app import helpers as hp

from photons_products import Products

from unittest import mock
import asyncio
import pytest
import time

describe "DeviceFinderDaemon":
    it "takes in a sender":
        stop_fut = hp.create_future()
        sender = mock.Mock(name="sender", stop_fut=stop_fut)

        daemon = DeviceFinderDaemon(sender)

        assert daemon.sender is sender
        assert isinstance(daemon.final_future, hp.ChildOfFuture)
        assert daemon.final_future.original_fut is sender.stop_fut

        assert daemon.search_interval == 20
        assert daemon.time_between_queries is None

        assert isinstance(daemon.finder, Finder)
        assert daemon.finder.sender is sender
        assert daemon.finder.final_future.original_fut is daemon.final_future
        assert daemon.finder.forget_after == 30
Esempio n. 29
0
    async def run(
        self,
        sig=None,
        expected_stdout=None,
        expected_stderr=None,
        expected_output=None,
        extra_argv=None,
        *,
        code,
    ):

        fut = hp.create_future()

        def ready(signum, frame):
            hp.get_event_loop().call_soon_threadsafe(fut.set_result, True)

        signal.signal(signal.SIGUSR1, ready)

        pipe = subprocess.PIPE
        cmd = [
            sys.executable,
            self.fle.name,
            self.out.name,
            str(os.getpid()),
            *[str(a) for a in (extra_argv or [])],
        ]

        p = subprocess.Popen(
            cmd,
            stdout=pipe,
            stderr=pipe,
        )

        await fut

        if sig is not None:
            p.send_signal(sig)

        p.wait(timeout=1)

        got_stdout = p.stdout.read().decode()
        got_stderr = p.stderr.read().decode().split("\n")

        redacted_stderr = []
        in_tb = False

        last_line = None
        for line in got_stderr:
            if last_line == "During handling of the above exception, another exception occurred:":
                redacted_stderr = redacted_stderr[:-5]
                last_line = line
                continue

            if in_tb and not line.startswith(" "):
                in_tb = False

            if line.startswith("Traceback"):
                in_tb = True
                redacted_stderr.append(line)
                redacted_stderr.append("  <REDACTED>")

            if not in_tb:
                redacted_stderr.append(line)

            last_line = line

        got_stderr = "\n".join(redacted_stderr)

        print("=== STDOUT:")
        print(got_stdout)
        print("=== STDERR:")
        print(got_stderr)

        def assertOutput(out, regex):
            if regex is None:
                return

            regex = dedent(regex).strip()

            out = out.strip()
            regex = regex.strip()
            assert len(out.split("\n")) == len(regex.split("\n"))
            pytest.helpers.assertRegex(f"(?m){regex}", out)

        if expected_output is not None:
            got = None
            if os.path.exists(self.out.name):
                with open(self.out.name) as o:
                    got = o.read().strip()
            assert got == expected_output.strip()

        assertOutput(got_stdout.strip(), expected_stdout)
        assertOutput(got_stderr.strip(), expected_stderr)

        assert p.returncode == code

        return got_stdout, got_stderr
Esempio n. 30
0

@pytest.fixture(autouse=True)
async def reset_devices(sender):
    for device in devices:
        await device.reset()
        devices.store(device).clear()
    sender.gatherer.clear_cache()


describe "Pipeline":

    @pytest.mark.parametrize("reference", [devices.serials, FoundSerials()])
    async it "does all messages at once if pipeline isn't used", sender, reference:
        called = []
        wait = hp.create_future()

        async def see_request(event):
            if event | DeviceMessages.SetPower:
                called.append(event.pkt.serial)
                if len(called) == 3 and not wait.done():
                    wait.set_result(True)
                    await asyncio.sleep(0)
                await wait

        isr1 = light1.io["MEMORY"].packet_filter.intercept_see_request(see_request)
        isr2 = light2.io["MEMORY"].packet_filter.intercept_see_request(see_request)
        isr3 = light3.io["MEMORY"].packet_filter.intercept_see_request(see_request)

        msgs = [
            DeviceMessages.SetPower(level=0),