예제 #1
0
                    async def __aexit__(s, exc_type, exc, tb):
                        if exc:
                            return False

                        if res is asyncio.CancelledError:
                            with assertRaises(res):
                                await V.task
                        elif type(res) is PhotonsAppError:
                            with assertRaises(PhotonsAppError, res.message):
                                await V.task
                        else:
                            assert (await V.task) == res
예제 #2
0
 async def check_result(expect=None):
     if expect is not None:
         assert (await result) == expect
     elif already_done is False:
         assert not result.done()
     elif already_done is True:
         assert (await result) == existing_result
     elif already_done == "exception":
         with assertRaises(ValueError, "Nope"):
             await result
     elif already_done == "cancelled":
         assert result.cancelled()
예제 #3
0
            for packet in packets:
                got = await V.session.determine_needed_transport(packet, services)
                assert got == [Services.UDP]

    describe "choose_transport":
        async it "complains if we can't determined need transport", V:
            determine_needed_transport = pytest.helpers.AsyncMock(name="determine_needed_transport")
            determine_needed_transport.return_value = []

            packet = mock.Mock(name="packet", protocol=9001, pkt_type=89)
            services = mock.Mock(name="services")

            msg = "Unable to determine what service to send packet to"
            kwargs = {"protocol": 9001, "pkt_type": 89}
            with assertRaises(NoDesiredService, msg, **kwargs):
                with mock.patch.object(
                    V.session, "determine_needed_transport", determine_needed_transport
                ):
                    await V.session.choose_transport(packet, services)

            determine_needed_transport.assert_awaited_once_with(packet, services)

        async it "returns the desired service or complains if can't be found", V:
            need = [Services.UDP]
            determine_needed_transport = pytest.helpers.AsyncMock(name="determine_needed_transport")
            determine_needed_transport.return_value = need

            udpservice = mock.Mock(name="udpservice")

            packet = mock.NonCallableMock(name="packet", spec=[])
예제 #4
0
            light1: [DeviceMessages.GetPower(), DeviceMessages.SetPower(level=65535)],
            light2: [DeviceMessages.GetPower(), DeviceMessages.SetPower(level=0)],
            light3: [DeviceMessages.GetPower(), DeviceMessages.SetPower(level=65535)],
        }

        await self.assertScript(sender, gen, expected=expected)

    async it "does not ignore exception in generator", sender:
        error = Exception("NOPE")

        async def gen(reference, sender, **kwargs):
            raise error
            yield DeviceMessages.GetPower()

        expected = {light1: [], light2: [], light3: []}
        with assertRaises(BadRun, _errors=[error]):
            await self.assertScript(sender, gen, expected=expected)

    async it "adds exception from generator to error_catcher", sender:
        got = []

        def err(e):
            got.append(e)

        error = Exception("NOPE")

        async def gen(reference, sender, **kwargs):
            raise error
            yield DeviceMessages.GetPower()

        expected = {light1: [], light2: [], light3: []}
예제 #5
0
                "  --> one = 1",
                "  || pkt = SetPower(ack=True,res=True,source=<NOT_SPECIFIED>,sequence=<NOT_SPECIFIED>,target=None)",
                "  ^^   level: 65535",
                "  :: other = [1, 2]",
                "  :: more = True",
            )

describe "Events":
    it "is a EventsHolder":
        assert isinstance(Events, EventsHolder)

    it "can register events":
        events = EventsHolder()
        assert events.events == {}

        with assertRaises(AttributeError):
            events.AMAZE_EVENT

        @events.register("AMAZE_EVENT")
        class Amaze:
            pass

        assert events.AMAZE_EVENT is Amaze

    it "can get a name for an event":
        events = EventsHolder()

        @events.register("AMAZE_EVENT")
        class Amaze:
            pass
예제 #6
0
    describe "adding a resolver":
        it "adds and overrides", register:
            typ = mock.Mock(name="typ")
            resolver = mock.Mock(name="resolver")
            register.add(typ, resolver)
            assert register.resolvers[typ] is resolver

            resolver2 = mock.Mock(name="resolver2")
            register.add(typ, resolver2)
            assert register.resolvers[typ] is resolver2

    describe "resolving":
        it "complains if the typ isn't registered", register:
            typ = mock.Mock(name="typ")
            with assertRaises(ResolverNotFound, wanted=typ):
                register.resolve(typ, "blah")

        it "uses registered resolver", register:
            ret = mock.Mock(name="ret")
            typ = mock.Mock(name="typ")
            resolver = mock.Mock(name="resolver", return_value=ret)
            register.add(typ, resolver)
            assert register.resolve(typ, "blah") is ret
            resolver.assert_called_once_with("blah")

    describe "getting a reference object":

        it "returns SpecialReference objects as is", register:

            class Reference(SpecialReference):
예제 #7
0
            pkt2 = msg(one=False, two="there")

            assert pkt1.Key == (1024, 52, '{"one": true, "two": "hello"}')
            assert pkt2.Key == (1024, 52, '{"one": false, "two": "there"}')

            # For efficiency, the Key is cached, so if you change the payload
            # The key stays the same, but we can delete the key for it to be recreated
            pkt1.two = "tree"
            assert pkt1.Key == (1024, 52, '{"one": true, "two": "hello"}')
            del pkt1.Key
            assert pkt1.Key == (1024, 52, '{"one": true, "two": "tree"}')

describe "MultiOptions":
    it "complains if we don't give it two functions":
        for a, b in [(None, None), (lambda: 1, None), (None, lambda: 1), (1, 2)]:
            with assertRaises(ProgrammerError, "Multi Options expects two callables"):
                MultiOptions(a, b)

    it "sets the two callables":
        determine_res_packet = mock.Mock(name="determine_res_packet")
        adjust_expected_number = mock.Mock(name="adjust_expected_number")
        options = MultiOptions(determine_res_packet, adjust_expected_number)

        assert options.determine_res_packet is determine_res_packet
        assert options.adjust_expected_number is adjust_expected_number

    it "has a Max helper":
        num = MultiOptions.Max(5)

        assert num([1]) == -1
        assert num([0, 1, 2, 3]) == -1
예제 #8
0
    it "passes through booleans":
        spec = boolean()
        meta = Meta.empty()

        assert spec.normalise(meta, False) is False
        assert spec.normalise(meta, [False]) is False
        assert spec.normalise(meta, True) is True
        assert spec.normalise(meta, [True]) is True

    it "complains about anything else":

        class Wat:
            pass

        for thing in ([], [1, 2], [True, False], {}, {1: 2}, lambda: 1, Wat, Wat()):
            with assertRaises(BadSpecValue):
                boolean().normalise(Meta.empty(), thing)

describe "str_ranges":
    it "converts comma separated pairs into list of tuples":
        wanted = "1-2,3-5.5,5,6.7-9,10.1-45.6"
        got = str_ranges().normalise(Meta.empty(), wanted)
        assert got == [(1.0, 2.0), (3.0, 5.5), (5.0, 5.0), (6.7, 9.0), (10.1, 45.6)]

    it "can take in list of tuples":
        wanted = [(1.0, 2.0), (3.0, 5.5), (5.0, 5.0), (6.7, 9.0), (10.1, 45.6)]
        got = str_ranges().normalise(Meta.empty(), wanted)
        assert wanted == got

    it "can take in list of strings":
        provided = ["1.0-2.0", "3.0-5.5", "5.0", "6.7-9.0", "10.1-45.6"]
예제 #9
0
from photons_protocol.packets import PacketSpecMetaKls, dictobj, Initial
from photons_protocol.types import Type as T

from photons_app.errors import ProgrammerError
from photons_app import helpers as hp

from delfick_project.errors_pytest import assertRaises
from delfick_project.norms import sb
from unittest import mock
import pytest
import uuid

describe "PacketSpecMetaKls":
    it "complains if we have fields that are already attributes":
        with assertRaises(
            ProgrammerError,
            r"Can't override attributes with fields\talready_attributes=\['items', 'values'\]",
        ):

            class Together(dictobj.PacketSpec):
                fields = [("items", T.Bool), ("values", T.Bool), ("one", T.Bool)]

        with assertRaises(
            ProgrammerError, r"Can't override attributes with fields\talready_attributes=\['one'\]"
        ):

            class Together2(dictobj.PacketSpec):
                fields = [("one", T.Bool)]

                def one(self):
                    pass
예제 #10
0
                d.start.assert_called_once_with()
                assert len(d.finish.mock_calls) == 0

        for d in devices:
            d.finish.assert_called_once_with()

    async it "finishes even on error":
        device1 = mock.Mock(name="device1")
        device2 = mock.Mock(name="device2")
        devices = [device1, device2]

        for d in devices:
            d.start = pytest.helpers.AsyncMock(name="start")
            d.finish = pytest.helpers.AsyncMock(name="finish")

        with assertRaises(ValueError, "NOPE"):
            async with WithDevices(devices):
                for d in devices:
                    d.start.assert_called_once_with()
                    assert len(d.finish.mock_calls) == 0
                raise ValueError("NOPE")

        for d in devices:
            d.finish.assert_called_once_with()

describe "pktkeys":
    it "can get us deduped keys to represent the packets":
        msg1 = DeviceMessages.SetPower(level=65535, source=1, sequence=2, target="d073d501")
        msg2 = DeviceMessages.SetLabel(label="bob", source=3, sequence=4, target="d073d502")
        msg3 = DeviceMessages.SetLabel(label="bob", source=5, sequence=6, target="d073d503")
        keys = pktkeys([msg1, msg2, msg3])
예제 #11
0
            assert thing == {"one": 2, "two": "yeap", "three": wat}

        it "complains if you try to reuse a command":
            store = Store()

            @store.command("thing")
            class Thing(store.Command):
                pass

            # Can use a child kls
            @store.command("another_path")
            class Other(Thing):
                pass

            # Can't use the same class though
            with assertRaises(CantReuseCommands):
                try:
                    store.command("another_path")(Thing)
                except CantReuseCommands as error:
                    assert error.reusing is Thing
                    raise

        it "works":
            store = Store()

            @store.command("thing", path="/v1")
            class Thing(store.Command):
                one = dictobj.Field(sb.integer_spec)
                two = dictobj.Field(sb.string_spec)

            class Spec1:
예제 #12
0
    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()
        assert not final_future.done()

        final_future = hp.create_future()
        streamer = hp.ResultStreamer(final_future)
        final_future.set_result(True)
        assert streamer.final_future.cancelled()

        final_future = hp.create_future()
        streamer = hp.ResultStreamer(final_future)
        final_future.set_exception(Exception("NOPE"))
        with assertRaises(Exception, "NOPE"):
            await streamer.final_future

        final_future = hp.create_future()
        streamer = hp.ResultStreamer(final_future)
        final_future.cancel()
        assert streamer.final_future.cancelled()

    describe "add generator":

        @pytest.fixture()
        async def V(self):
            class V:
                final_future = hp.create_future()
                error_catcher = mock.Mock(name="error_catcher")
예제 #13
0
        assert found != otherfound

        otherfound["d073d5000001"] = 1
        otherfound["d073d5000002"] = 2
        otherfound["d073d5000003"] = 3
        otherfound["d073d5000004"] = 4
        assert found == otherfound

        otherfound["d073d5000004"] = 5
        assert found != otherfound

        found["d073d5000005"] = 6
        assert len(found) == 5

    it "has getitem", found:
        with assertRaises(KeyError):
            found["d073d5000001"]

        services = mock.Mock(name="services")
        found["d073d5000001"] = services

        assert found["d073d5000001"] is services
        assert found["d073d500000111"] is services
        assert found[binascii.unhexlify("d073d5000001")] is services
        assert found[binascii.unhexlify("d073d500000122")] is services

    it "has setitem", found:
        found["d073d5000001"] = 1
        assert found["d073d5000001"] == 1

        found["d073d500000122"] = 2
예제 #14
0
                    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)

        with assertRaises(PhotonsAppError, "YO"):
            T.create(collector).run_loop(collector=collector)

        assert called == [1, 2, 3, 4, "c1a", "c1b", "c2a", "c2b"]

    it "cleans up after we finish task if it's cancelled outside", collector:

        called = []

        class T(Task):
            async def execute_task(self, collector, **kwargs):
                called.append(1)

                async def cleanup1():
                    called.append("c1a")
                    fut = hp.create_future()
예제 #15
0
            result = list(
                database.execute("SELECT * FROM thingmodel WHERE one=:one", {"one": "one"})
            )
            assert result == [(1, "one", 1)]

    describe "queries":
        it "has methods for doing stuff with the database", database, ThingModel:
            one = database.queries.create_thing_model(one="one", two=True)
            database.add(one)
            database.commit()

            two, made = database.queries.get_or_create_thing_model(one="one", two=True)
            assert made == False
            assert one.id == two.id

            three, made = database.queries.get_or_create_thing_model(one="two", two=True)
            assert made == True
            database.add(three)
            database.commit()

            made = database.queries.get_thing_models().order_by(ThingModel.one.asc()).all()
            assert [t.as_dict() for t in made] == [t.as_dict() for t in (one, three)]

            one_got = database.queries.get_thing_model(one="one")
            assert one_got.as_dict() == one.as_dict()
            assert one_got.id == one.id

            with assertRaises(sqlalchemy.orm.exc.MultipleResultsFound):
                database.queries.get_one_thing_model(two=True)
예제 #16
0
            {"start_index": 10 + 23, "end_index": 10 + 23},
            {"start_index": 10 + 24, "end_index": 10 + 24},
            {"start_index": 10 + 25, "end_index": 10 + 25},
            {"start_index": 10 + 26, "end_index": 10 + 26},
            {"start_index": 10 + 27, "end_index": 10 + 27},
            {"start_index": 10 + 28, "end_index": 10 + 28},
        ]

        for e, o in zip(expected_old, plan.set_color_old):
            for k, v in e.items():
                assert v == o[k]

        assert plan.set_color_new.zone_index == 10

    async it "complains if we have more than 82 colors":
        with assertRaises(PhotonsAppError, "colors can only go up to 82 colors", got=87):
            SetZonesPlan([["red", 80], ["blue", 7]])

    async it "complains if we have no colors":
        with assertRaises(PhotonsAppError, "No colors were specified"):
            SetZonesPlan([])

    async it "can create messages to send back", specifier:
        plan = SetZonesPlan(specifier)

        def make(device, options):
            return type("Capability", (Capability,), options)(device.cap.product)

        instance1 = plan.Instance(
            light1.serial,
            plan,
예제 #17
0
    it "returns as is if the value is already a Services", meta, spec:
        val = Services.UDP
        assert spec.normalise(meta, val) is val

    it "returns the enum value if it matches", meta, spec:
        val = "UDP"
        assert spec.normalise(meta, val) is Services.UDP

    it "complains if we don't have a match", meta, spec:
        msg = "Unknown service type"

        services = sorted([s.name for s in Services if not s.name.startswith("RESERVED")])
        assert len(services) > 0

        kwargs = dict(want="WAT", available=services)
        with assertRaises(BadSpecValue, msg, **kwargs):
            spec.normalise(meta, "WAT")

describe "hardcoded_discovery_spec":

    @pytest.fixture()
    def spec(self):
        return do.hardcoded_discovery_spec()

    @pytest.fixture()
    def ret(self):
        return mock.Mock(name="ret")

    @pytest.fixture()
    def fake_spec(self, ret):
        fake_spec = mock.Mock(name="fake_spec")
예제 #18
0
        assert thing.progress_cb is progress_cb
        assert thing.request_handler is request_handler
        assert thing.path == "/v1"
        assert thing.store is store

        assert thing.request_future.done()

    async it "injected fields complain if they don't exist":
        store2 = store.clone()
        progress_cb = mock.Mock(name="progress_cb")
        request_handler = mock.Mock(name="request_handler")
        commander = Commander(store2)

        with assertRaises(
            BadOptionFormat,
            "Can't find key in options",
            chain=["body.args.notexisting"],
            key="notexisting",
        ):
            await commander.executor(progress_cb, request_handler).execute(
                "/v1", {"command": "fields_are_required"}
            )
            assert False, "expected an error"

    async it "injected fields complain if they don't match format_into option":
        store2 = store.clone()
        progress_cb = mock.Mock(name="progress_cb")
        request_handler = mock.Mock(name="request_handler")
        commander = Commander(store2)

        try:
            await commander.executor(progress_cb, request_handler, option="asdf").execute(
예제 #19
0
    async it "returns the result of waiting on the coroutine":
        val = str(uuid.uuid1())

        async def func():
            return val

        res = await hp.async_with_timeout(func(), timeout=10)
        assert res == val

    async it "cancels the coroutine if it doesn't respond":

        async def func():
            await asyncio.sleep(2)

        start = time.time()
        with assertRaises(asyncio.CancelledError):
            await hp.async_with_timeout(func(), timeout=0.1)
        assert time.time() - start < 0.5

    async it "cancels the coroutine and raises timeout_error":
        error = PhotonsAppError("Blah")

        async def func():
            try:
                await asyncio.sleep(2)
            except asyncio.CancelledError:
                assert False, "Expected it to just raise the error rather than cancelling first"

        start = time.time()
        with assertRaises(PhotonsAppError, "Blah"):
            await hp.async_with_timeout(func(), timeout=0.1, timeout_error=error)
예제 #20
0
        assert val_to_bitarray("d073d5", "test") == expected

    it "creates bitarray from bytes":
        expected = bitarray(endian="little")
        bts = binascii.unhexlify("d073d5")
        expected.frombytes(bts)
        assert val_to_bitarray(bts, "test") == expected

    it "creates bitarray from sb.NotSpecified":
        expected = bitarray(endian="little")
        assert val_to_bitarray(sb.NotSpecified, "test") == expected

    it "complains otherwise":
        doing = mock.Mock(name="doing")
        for val in (0, 1, None, True, False, [], [1], {1: 2}, lambda: 1):
            with assertRaises(BadConversion, "Couldn't get bitarray from a value", doing=doing):
                val_to_bitarray(val, doing)

describe "BitarraySlice":

    @pytest.fixture()
    def slce(self):
        name = mock.Mock(name="name")
        typ = mock.Mock(name="typ")
        val = mock.Mock(name="val")
        size_bits = mock.Mock(name="size_bits")
        group = mock.Mock(name="group")
        return BitarraySlice(name, typ, val, size_bits, group)

    it "takes in things":
        name = mock.Mock(name="name")
예제 #21
0
        es = []

        def ec(e):
            es.append(e)

        with catch_errors(ec):
            pass
        assert es == []

        with catch_errors(es):
            pass
        assert es == []

    it "throws the error if just one":
        with assertRaises(ValueError, "NOPE"):
            with catch_errors():
                raise ValueError("NOPE")

    it "merges multiple of the same error together":
        e1 = PhotonsAppError("yeap", a=1)
        e2 = PhotonsAppError("yeap", a=1)

        with assertRaises(PhotonsAppError, "yeap", a=1):
            with catch_errors() as ec:
                hp.add_error(ec, e1)
                raise e2

        with assertRaises(PhotonsAppError, "yeap", a=1):
            with catch_errors() as ec:
                hp.add_error(ec, e1)
예제 #22
0
    it "can match nested lists":
        for val in ([[]], ["asdf", [1]], [["asdf", True], [1]]):
            assert json_spec.normalise(Meta.empty(), val) == val

    it "can match dictionaries":
        for val in ({}, {"1": "2", "2": 2, "3": False}):
            assert json_spec.normalise(Meta.empty(), val) == val

    it "can match nested dictionaries":
        val = {"asdf": {"adf": {"asdf": 2, "adf": False, "eieu": None}}}
        assert json_spec.normalise(Meta.empty(), val) == val

    it "complains about things that aren't json like objects, callables and non string keys":
        for val in (type("adf", (object,), {}), any, json, lambda: 1):
            with assertRaises(BadSpecValue):
                json_spec.normalise(Meta.empty(), val)

        try:
            json_spec.normalise(Meta.empty(), {"one": {1: 2}})
            assert False, "Expected an error"
        except BadSpecValue as error:
            assert error.errors[0].errors[0].message == "Expected a string"

describe "Type":
    it "takes in struct_format and conversion":
        struct_format = mock.Mock(name="struct_format")
        conversion = mock.Mock(name="conversion")
        t = Type(struct_format, conversion)
        assert t.struct_format is struct_format
        assert t.conversion is conversion
예제 #23
0
            loop = photons_app.loop
            assert loop.get_debug()

    describe "final_future":
        it "belongs to the loop":
            photons_app = self.make_photons_app()
            final_future = photons_app.final_future
            assert final_future._loop is photons_app.loop

    describe "extra_as_json":
        it "converts extra into json dictionary":
            photons_app = self.make_photons_app(extra='{"one": 2, "two": "three"}')
            assert photons_app.extra_as_json == {"one": 2, "two": "three"}

        it "complains if extra is not valid json":
            with assertRaises(BadOption, "The options after -- wasn't valid json"):
                self.make_photons_app(extra="{").extra_as_json

        it "can read json from a file":
            with hp.a_temp_file() as fle:
                fle.write(b'{"power": "off"}')
                fle.flush()
                assert self.make_photons_app(extra=f"file://{fle.name}").extra_as_json == {
                    "power": "off"
                }

                path = os.path.relpath(fle.name, os.getcwd())
                assert not path.startswith("/")
                assert self.make_photons_app(extra=f"file://{path}").extra_as_json == {
                    "power": "off"
                }
예제 #24
0
        cap3 = cap2(firmware_major=3, firmware_minor=4)
        assert cap2 != cap3

        product2 = mock.Mock(name="product")
        cap4 = base.Capability(product2)
        assert cap != cap4

    it "returns no items by default":
        product = mock.Mock(name="product")
        cap = base.Capability(product)
        assert list(cap.items()) == []

describe "Product":
    it "complains about not having a cap":
        with assertRaises(
            IncompleteProduct, "Product doesn't have a capability specified", name="P"
        ):

            class P(base.Product):
                pass

    it "complains about attributes not implemented":
        with assertRaises(
            IncompleteProduct, "Attribute wasn't overridden", attr="family", name="P"
        ):

            class P(base.Product):
                class cap(base.Capability):
                    pass

    it "sets the cap as an instance of the cap class":
예제 #25
0
describe "CommandSplitter":
    it "can format argv":
        command = "{@:2}:{@:1} {@:3:}"
        result = CommandSplitter(
            {"argv": ["my_script", "one", "two", "three", "four"]}, command
        ).split()
        assert result == ["two:one", "three", "four"]

        command = "{@:2:4}:{@:1} {@:4:}"
        result = CommandSplitter(
            {"argv": ["my_script", "one", "two", "three", "four", "five"]}, command
        ).split()
        assert result == ["two", "three:one", "four", "five"]

    it "can complain about an env specifier without a name":
        with assertRaises(Exception, "env specifier used without saying what variable is needed"):
            command = "{:env}"
            CommandSplitter({"argv": ["my_script"]}, command).split()

    it "can complain if an environment variable is needed but doesn't exist":
        with pytest.helpers.modified_env(THING=None):
            with assertRaises(
                SystemExit, "This script requires you have a 'THING' variable in your environment"
            ):
                command = "{THING:env}"
                CommandSplitter({"argv": ["my_script"]}, command).split()

    it "doesn't complain if the environment variable exists but is empty":
        with pytest.helpers.modified_env(THING=""):
            command = "thing={THING:env}"
            assert CommandSplitter({"argv": ["my_script"]}, command).split() == ["thing="]
예제 #26
0
파일: test_db.py 프로젝트: delfick/photons
        await runner.database.request(do_set)

        async def do_get(session, query):
            return (await query.get_one_thing()).as_dict()

        got = await runner.database.request(do_get)
        assert got == {"one": "one", "two": True}

    async it "retries on OperationalError", runner:
        tries = [True, True]

        async def do_error(session, query):
            tries.pop(0)
            raise sqlalchemy.exc.OperationalError("select", {}, "")

        with assertRaises(sqlalchemy.exc.OperationalError):
            await runner.database.request(do_error)

        assert tries == []

    async it "can work after the first OperationalError", runner:
        tries = [True, True]

        async def do_error(session, query):
            tries.pop(0)
            if len(tries) == 1:
                raise sqlalchemy.exc.OperationalError("select", {}, "")
            else:
                one = await query.create_thing(one="one", two=True)
                session.add(one)
예제 #27
0
    it "can get a path object", attrs:
        path = attrs.attrs_path("one", "two", 3, "four")
        assert isinstance(path, Path)
        assert path.attrs is attrs
        assert path.parts == ["one", "two", 3, "four"]

    async it "says if something is inside _attrs", attrs:
        assert "one" not in attrs
        await attrs.attrs_apply(attrs.attrs_path("one").changer_to(3), event=None)
        assert "one" in attrs
        assert attrs.one == 3
        assert attrs["one"] == 3

    it "complains if you try to set things on the attrs with item or attr syntax", attrs:
        assert "nup" not in attrs
        with assertRaises(TypeError, "'Attrs' object does not support item assignment"):
            attrs["nup"] = 3
        assert "nup" not in attrs

        with assertRaises(AttributeError):
            attrs.nup = 3
        assert "nup" not in attrs

    async it "can get attributes with item and attr syntax", attrs:
        with assertRaises(AttributeError, "No such attribute thing"):
            attrs.thing
        with assertRaises(KeyError, "thing"):
            attrs["thing"]

        await attrs.attrs_apply(
            attrs.attrs_path("thing").changer_to(3),
예제 #28
0
        fut.set_exception(TypeError("NOPE"))
        assert fut.done()
        fut.reset()
        assert not fut.done()

        fut.cancel()
        assert fut.done()
        fut.reset()
        assert not fut.done()

    async it "can get and set a result":
        fut = hp.ResettableFuture()
        fut.set_result(True)
        assert fut.result() is True

        with assertRaises(hp.InvalidStateError):
            fut.set_result(False)

        assert await fut is True

        fut.reset()
        assert not fut.done()
        fut.set_result(False)
        assert fut.result() is False

        assert await fut is False

    async it "can get and set an exception":
        fut = hp.ResettableFuture()
        error = ValueError("NOPE")
        fut.set_exception(error)
예제 #29
0
                else:
                    assert filtr[field] is sb.NotSpecified

        it "defaults everything to NotSpecified":
            filtr = Filter.empty()
            assert len(filtr.fields) == 16
            self.assertFltrMatches(filtr, {})

        describe "from_json_str":
            it "treats the string as a json object":
                want = {"label": "kitchen", "location_name": ["one", "two"], "hue": "20-50"}
                expect = {"label": ["kitchen"], "location_name": ["one", "two"], "hue": [(20, 50)]}
                self.assertFltrMatches(Filter.from_json_str(json.dumps(want)), expect)

            it "complains if the string is not valid json":
                with assertRaises(InvalidJson):
                    Filter.from_json_str("{")

            it "complains if the string is not a dictionary":
                for s in ('"wat"', "[]", "1"):
                    # Make sure it's valid json
                    json.dumps(s)

                    # And make sure it complains it's not a dictionary
                    with assertRaises(InvalidJson, "Expected a dictionary"):
                        Filter.from_json_str(s)

        describe "from_key_value_str":
            it "treats the key,value as dictionary items":
                want = "label=bathroom,hallway location_id=identifier1 saturation=0.7,0.8-1"
                expect = {
예제 #30
0
        assert attrs.wat is val

        device.validate_attr.reset_mock()
        val2 = mock.Mock(name="val")
        attrs.wat2 = val2
        device.validate_attr.assert_called_once_with("wat2", val2)
        assert attrs.wat is val
        assert attrs.wat2 is val2

    it "doesn't set key if validate_attr raises an error", device, attrs:
        assert attrs._attrs == {}

        attrs.wat = 2
        attrs["things"] = 3
        expected = {"wat": 2, "things": 3}
        assert attrs._attrs == expected

        device.validate_attr.side_effect = ValueError("NOPE")

        with assertRaises(ValueError, "NOPE"):
            attrs.nope = 2

        with assertRaises(AttributeError):
            attrs.nope

        with assertRaises(ValueError, "NOPE"):
            attrs["hello"] = 3

        with assertRaises(KeyError):
            attrs["hello"]