Esempio n. 1
0
def test_discovery_method_local():
    """All TDs contained in the Servient are returned when using the local
    discovery method without defining the fragment nor the query fields."""

    servient = Servient(dnssd_enabled=False)
    wot = WoT(servient=servient)
    wot.produce(ThingFragment(TD_DICT_01))
    wot.produce(ThingFragment(TD_DICT_02))

    future_done, found = tornado.concurrent.Future(), []

    def resolve():
        len(found) == 2 and not future_done.done() and future_done.set_result(
            True)

    @tornado.gen.coroutine
    def test_coroutine():
        thing_filter = ThingFilterDict(method=DiscoveryMethod.LOCAL)
        observable = wot.discover(thing_filter)

        subscription = observable.subscribe(
            on_next=lambda td_str: found.append(ThingDescription(td_str)
                                                ) or resolve())

        yield future_done

        assert_equal_td_sequences(found, [TD_DICT_01, TD_DICT_02])

        subscription.dispose()

    run_test_coroutine(test_coroutine)
Esempio n. 2
0
    def test_coroutine():
        wot_01 = yield servient_01.start()
        wot_02 = yield servient_02.start()

        wot_01.produce(ThingFragment(TD_DICT_01)).expose()
        wot_01.produce(ThingFragment(TD_DICT_02)).expose()

        thing_filter = ThingFilterDict(method=DiscoveryMethod.MULTICAST)

        observable = wot_02.discover(thing_filter,
                                     dnssd_find_kwargs={
                                         "min_results": 1,
                                         "timeout": 5
                                     })

        subscription = observable.subscribe(
            on_next=lambda td_str: found.append(ThingDescription(td_str)
                                                ) or resolve())

        yield future_done

        assert_equal_td_sequences(found, [TD_DICT_01, TD_DICT_02])

        subscription.dispose()

        yield servient_01.shutdown()
        yield servient_02.shutdown()
Esempio n. 3
0
    def __init__(self, doc):
        """Constructor.
        Validates that the document conforms to the TD schema."""

        self._doc = json.loads(doc) if isinstance(doc, (six.string_types, bytes)) else doc
        self._thing_fragment = ThingFragment(self._doc)

        self.validate(doc=self._thing_fragment.to_dict())
Esempio n. 4
0
def test_discovery_fragment():
    """The Thing filter fragment attribute enables discovering Things by matching TD fields."""

    servient = Servient(dnssd_enabled=False)
    wot = WoT(servient=servient)
    wot.produce(ThingFragment(TD_DICT_01))
    wot.produce(ThingFragment(TD_DICT_02))

    def first(thing_filter):
        """Returns the first TD discovery for the given Thing filter."""

        future_done, found = tornado.concurrent.Future(), []

        def resolve():
            not future_done.done() and future_done.set_result(True)

        @tornado.gen.coroutine
        def discover_first():
            observable = wot.discover(thing_filter)

            subscription = observable.subscribe(
                on_next=lambda td_str: found.append(ThingDescription(td_str)
                                                    ) or resolve())

            yield future_done

            subscription.dispose()

            assert len(found)

            raise tornado.gen.Return(found[0])

        return tornado.ioloop.IOLoop.current().run_sync(
            discover_first, timeout=TIMEOUT_DISCOVER)

    fragment_td_pairs = [({
        "name": TD_DICT_01.get("name")
    }, TD_DICT_01), ({
        "version": {
            "instance": "2.0.0"
        }
    }, TD_DICT_02), ({
        "id": TD_DICT_02.get("id")
    }, TD_DICT_02), ({
        "security": [{
            "scheme": "psk"
        }]
    }, TD_DICT_01)]

    for fragment, td_expected in fragment_td_pairs:
        td_found = first(
            ThingFilterDict(method=DiscoveryMethod.LOCAL, fragment=fragment))
        assert_equal_tds(td_found, td_expected)
Esempio n. 5
0
 def __init__(self, thing_fragment=None, **kwargs):
     self._thing_fragment = thing_fragment if thing_fragment else ThingFragment(
         **kwargs)
     self._properties = {}
     self._actions = {}
     self._events = {}
     self._init_fragment_interactions()
Esempio n. 6
0
def test_thing_fragment():
    """Thing fragment dictionaries can be represented and serialized."""

    thing_fragment = ThingFragment(THING_INIT)

    assert thing_fragment.id == THING_INIT["id"]
    assert thing_fragment.title == THING_INIT["title"]
    assert thing_fragment.description == THING_INIT["description"]
    assert isinstance(next(six.itervalues(thing_fragment.properties)),
                      PropertyFragmentDict)
    assert isinstance(next(six.itervalues(thing_fragment.actions)),
                      ActionFragmentDict)
    assert isinstance(next(six.itervalues(thing_fragment.events)),
                      EventFragmentDict)
    assert json.dumps(thing_fragment.to_dict())
    assert next(six.itervalues(thing_fragment.to_dict()["properties"]))["type"]
    assert thing_fragment.version.instance == THING_INIT["version"]["instance"]

    with pytest.raises(Exception):
        ThingFragment({})
Esempio n. 7
0
def test_thing_fragment_getters_setters():
    """ThingFragment attributes can be get and set from the ExposedThing."""

    thing_fragment = ThingFragment({
        "id": uuid.uuid4().urn,
        "name": Faker().pystr(),
        "description": Faker().pystr(),
        "properties": {
            uuid.uuid4().hex: {
                "description": Faker().pystr(),
                "type": DataType.STRING
            }
        }
    })

    thing = Thing(thing_fragment=thing_fragment)
    exp_thing = ExposedThing(servient=Servient(), thing=thing)

    assert exp_thing.name == thing_fragment.name
    assert exp_thing.description == thing_fragment.description
    assert list(exp_thing.properties) == list(
        six.iterkeys(thing_fragment.properties))

    name_original = thing_fragment.name
    name_updated = Faker().pystr()

    description_original = thing_fragment.description
    description_updated = Faker().pystr()

    exp_thing.name = name_updated
    exp_thing.description = description_updated

    assert exp_thing.name == name_updated
    assert exp_thing.name != name_original
    assert exp_thing.description == description_updated
    assert exp_thing.description != description_original

    with pytest.raises(AttributeError):
        # noinspection PyPropertyAccess
        exp_thing.id = Faker().pystr()

    with pytest.raises(AttributeError):
        # noinspection PyPropertyAccess
        exp_thing.properties = Faker().pylist()

    with pytest.raises(AttributeError):
        # noinspection PyPropertyAccess
        exp_thing.actions = Faker().pylist()

    with pytest.raises(AttributeError):
        # noinspection PyPropertyAccess
        exp_thing.events = Faker().pylist()
Esempio n. 8
0
def test_produce_model_thing_template():
    """Things can be produced from ThingTemplate instances."""

    thing_id = Faker().url()
    thing_name = Faker().sentence()

    thing_template = ThingFragment({"id": thing_id, "name": thing_name})

    servient = Servient()
    wot = WoT(servient=servient)

    exp_thing = wot.produce(thing_template)

    assert servient.get_exposed_thing(thing_id)
    assert exp_thing.id == thing_id
    assert exp_thing.name == thing_name
Esempio n. 9
0
def test_thing_fragment_setters():
    """Thing fragment properties can be set."""

    thing_fragment = ThingFragment(THING_INIT)

    with pytest.raises(AttributeError):
        thing_fragment.id = Faker().pystr()

    assert thing_fragment.title == THING_INIT["title"]

    title = Faker().pystr()

    # noinspection PyPropertyAccess
    thing_fragment.title = title

    assert thing_fragment.title != THING_INIT["title"]
    assert thing_fragment.title == title

    prop_fragment = PropertyFragmentDict(description=Faker().pystr(),
                                         type=DataType.NUMBER)
    props_updated = {Faker().pystr(): prop_fragment}

    # noinspection PyPropertyAccess
    thing_fragment.properties = props_updated

    assert next(six.itervalues(
        thing_fragment.properties)).description == prop_fragment.description

    security_updated = [SecuritySchemeDict(scheme=SecuritySchemeType.PSK)]

    # noinspection PyPropertyAccess
    thing_fragment.security = security_updated

    assert thing_fragment.security[0].scheme == security_updated[0].scheme

    version_updated = VersioningDict(instance=Faker().pystr())

    # noinspection PyPropertyAccess
    thing_fragment.version = version_updated

    assert thing_fragment.version.instance == version_updated.instance
Esempio n. 10
0
    def thing_fragment(self):
        """The ThingFragment dictionary of this Thing."""

        def interaction_to_json(intrct):
            """Returns the JSON serialization of an Interaction instance."""

            ret = intrct.interaction_fragment.to_dict()

            ret.update({
                "forms": [form.form_dict.to_dict() for form in intrct.forms]
            })

            return ret

        doc = self._thing_fragment.to_dict()

        doc.update({
            "properties": {
                key: interaction_to_json(val)
                for key, val in six.iteritems(self.properties)
            }
        })

        doc.update({
            "actions": {
                key: interaction_to_json(val)
                for key, val in six.iteritems(self.actions)
            }
        })

        doc.update({
            "events": {
                key: interaction_to_json(val)
                for key, val in six.iteritems(self.events)
            }
        })

        return ThingFragment(doc)
Esempio n. 11
0
class ThingDescription(object):
    """Class that represents a Thing Description document.
    Contains logic to validate and transform a Thing to a serialized TD and vice versa."""

    def __init__(self, doc):
        """Constructor.
        Validates that the document conforms to the TD schema."""

        self._doc = json.loads(doc) if isinstance(doc, (six.string_types, bytes)) else doc
        self._thing_fragment = ThingFragment(self._doc)

        self.validate(doc=self._thing_fragment.to_dict())

    @classmethod
    def validate(cls, doc):
        """Validates the given Thing Description document against its schema.
        Raises ValidationError if validation fails."""

        try:
            jsonschema.validate(doc, SCHEMA_THING)
        except (jsonschema.ValidationError, TypeError) as ex:
            raise InvalidDescription(str(ex))

    @classmethod
    def from_thing(cls, thing):
        """Builds an instance of a JSON-serialized Thing Description from a Thing object."""

        return ThingDescription(thing.thing_fragment.to_dict())

    def __getattr__(self, name):
        """Search for members that raised an AttributeError in
        the internal ThingFragment before propagating the exception."""

        return getattr(self._thing_fragment, name)

    def to_dict(self):
        """Returns the JSON Thing Description as a dict."""

        return self._thing_fragment.to_dict()

    def to_str(self):
        """Returns the JSON Thing Description as a string."""

        return json.dumps(self._thing_fragment.to_dict())

    def to_thing_fragment(self):
        """Returns a ThingFragment dictionary built from this TD."""

        return self._thing_fragment

    def build_thing(self):
        """Builds a new Thing object from the serialized Thing Description."""

        return Thing(thing_fragment=self.to_thing_fragment())

    def get_forms(self, name):
        """Returns a list of FormDict for the interaction that matches the given name."""

        if name in self.properties:
            return self.get_property_forms(name)

        if name in self.actions:
            return self.get_action_forms(name)

        if name in self.events:
            return self.get_event_forms(name)

        return []

    def get_property_forms(self, name):
        """Returns a list of FormDict for the property that matches the given name."""

        return self.properties[name].forms

    def get_action_forms(self, name):
        """Returns a list of FormDict for the action that matches the given name."""

        return self.actions[name].forms

    def get_event_forms(self, name):
        """Returns a list of FormDict for the event that matches the given name."""

        return self.events[name].forms