Example #1
0
def test_property_illegal_push(context_mock):
    prop_no_push = Property(name=DEFAULT_PROPERTY_NAME,
                            default_value=DEFAULT_PROPERTY_VALUE,
                            allow_push=False)
    prop_no_push.set_parent_path(DEFAULT_MODULE_NAME)
    wrapper = PropertyWrapper(prop=prop_no_push,
                              ctx=context_mock,
                              allow_read=True,
                              allow_write=True)
    with LogCapture(attributes=strip_prefix) as log_capture:
        assert not wrapper.push(child=Property(name=CHILD_PROPERTY_NAME))
        log_capture.check(
            f'Unauthorized push in property {DEFAULT_MODULE_NAME}:{DEFAULT_PROPERTY_NAME}!',
        )
Example #2
0
def test_flag_property(context_mock):
    prop_base = Property(name="flag_prop", is_flag_property=True)
    prop_base.set_parent_path(DEFAULT_MODULE_NAME)
    prop_wrapper = PropertyWrapper(prop=prop_base,
                                   ctx=context_mock,
                                   allow_read=True,
                                   allow_write=True)
    assert (prop_base._lock.locked())

    prop_wrapper.set(True)
    assert (prop_wrapper.get() is True)
    context_mock.emit.assert_any_call(
        SignalRef(f"{prop_wrapper.prop.id()}:changed"),
        parents=None,
        wipe=True,
        payload=True,
        boring=False)
    context_mock.emit.assert_any_call(
        SignalRef(f"{prop_wrapper.prop.id()}:true"),
        parents=None,
        wipe=True,
        boring=False)

    context_mock.emit.reset_mock()
    prop_wrapper.set(False)
    assert (prop_wrapper.get() is False)
    context_mock.emit.assert_any_call(
        SignalRef(f"{prop_wrapper.prop.id()}:changed"),
        parents=None,
        wipe=True,
        payload=False,
        boring=False)
    context_mock.emit.assert_any_call(
        SignalRef(f"{prop_wrapper.prop.id()}:false"),
        parents=None,
        wipe=True,
        boring=False)

    context_mock.emit.reset_mock()
    prop_wrapper.set(None)
    assert (prop_wrapper.get() is None)
    context_mock.emit.assert_called_once_with(
        SignalRef(f"{prop_wrapper.prop.id()}:changed"),
        parents=None,
        wipe=True,
        payload=None,
        boring=False)
Example #3
0
def test_property_child(under_test_read_write: PropertyWrapper,
                        default_property_base, context_mock):
    assert under_test_read_write.push(
        Property(name=CHILD_PROPERTY_NAME,
                 default_value=DEFAULT_PROPERTY_VALUE))
    assert list(under_test_read_write.enum())[0] == CHILD_PROPERTY_ID
    assert under_test_read_write.prop.children[CHILD_PROPERTY_NAME].read(
    ) == DEFAULT_PROPERTY_VALUE
Example #4
0
    def add_prop(self, *, prop: Property) -> None:
        """
        Add a copy of a property to this context. An error message will be generated, if a property with
         the same name has already been added previously. Note: Context will adopt a __copy__
         of the given property, the actual property will not be changed.

        * `prop`: The property object that should be added.
        """
        # prop = prop.clone()
        if prop.id() in self._properties:
            logger.error(f"Attempt to add property {prop.id()} twice!")
            return
        # Do not adopt the
        with self._lock:
            # register property
            self._properties[prop.id()] = prop
            # register all of the property's signals
            for signal in prop.signals():
                self._add_sig(signal)
Example #5
0
    def rm_prop(self, *, prop: Property) -> None:
        """
        Remove a property from this context.
        Generates error message, if the property was not added with add_prop() to the context previously

        * `prop`: The property to remove.object
        """
        if prop.id() not in self._properties:
            logger.error(f"Attempt to remove unknown property {prop.id()}!")
            return
        # remove property from context
        self._properties.pop(prop.id())
        states_to_remove: Set[State] = set()
        with self._lock:
            # remove all of the property's signals
            for signal in prop.signals():
                self._rm_sig(signal)
            # remove all states that depend upon property
            for st in self._activations_per_state:
                if prop.id() in st.get_all_props_ids():
                    states_to_remove.add(st)
        for st in states_to_remove:
            self.rm_state(st=st)
Example #6
0
    def push(self, child: Property):
        """
        Add a child to the property or to children of the property

        * `child`: Parent-less, child-less property object to add.
         Name of the child must be unique among existing children of this property.

        **Returns:** True if the push was successful, False otherwise
        """
        if not self.allow_write:
            logger.error(
                f"Unauthorized push access in property-wrapper {self.prop.id()}!"
            )
            return False
        if self.prop.push(child):
            self.ctx.emit(self.prop.pushed(),
                          parents=self.spike_parents,
                          wipe=False,
                          payload=child.id(),
                          boring=self.boring)
            return True
        return False
Example #7
0
    def push(self, parent_property_or_path: Union[str, Property],
             child: Property):
        """
        Add a child to a property.
         Note: Child must not yet have a parent or children of itself.
          Write-access to parent is needed.

        * `parent_property_or_path`: (Path of the) parent property that should receive the new child.

        * `child`: Parent-less, child-less property object to add.

        **Returns:** True if the push was successful, False otherwise
        """
        if child.parent_path:
            logger.error(
                f"State {self.state.name} attempted to push child property {child.name} to parent {parent_property_or_path}, but it already has parent {child.parent_path}!"
            )
            return False
        if isinstance(parent_property_or_path, Property):
            parent_property_or_path = parent_property_or_path.id()
        if parent_property_or_path in self.properties:
            if self.properties[parent_property_or_path].push(child):
                self.properties[child.id()] = PropertyWrapper(
                    prop=child,
                    ctx=self.ctx,
                    spike_parents=self.spike_parents,
                    allow_read=self.properties[parent_property_or_path].
                    allow_read,
                    allow_write=self.properties[parent_property_or_path].
                    allow_write,
                    boring=self.state.boring)
                self.ctx.add_prop(prop=child)
                return True
        else:
            logger.error(
                f'State {self.state.name} attempted to add child-property {child.name} to non-accessible parent {parent_property_or_path}!'
            )
            return False
Example #8
0
def test_property(under_test_read_only: PropertyWrapper,
                  default_property_base: Property):
    assert (default_property_base.id() ==
            f"{DEFAULT_MODULE_NAME}:{DEFAULT_PROPERTY_NAME}")
    assert (not default_property_base._lock.locked())
    assert (default_property_base.read() == DEFAULT_PROPERTY_VALUE)
Example #9
0
def default_property_base():
    prop = Property(name=DEFAULT_PROPERTY_NAME,
                    default_value=DEFAULT_PROPERTY_VALUE)
    prop.set_parent_path(DEFAULT_MODULE_NAME)
    return prop
Example #10
0
CORE_MODULE_CONFIG = {IMPORT_MODULES_CONFIG_KEY: [], TICK_RATE_CONFIG_KEY: 20}

with Module(name="core", config=CORE_MODULE_CONFIG) as core_module:
    """
    The startup signal, which is fired once when `Context.run()` is executed.
    """
    sig_startup = Signal("startup")
    """
    The shutdown signal, which is fired once when `Context.shutdown()` is called.
    """
    sig_shutdown = Signal("shutdown")

    prop_pressure = Property(name="pressure",
                             allow_read=True,
                             allow_write=True,
                             allow_push=False,
                             allow_pop=False,
                             default_value=False,
                             always_signal_changed=False,
                             is_flag_property=True)

    prop_activity = Property(name="activity",
                             allow_read=True,
                             allow_write=True,
                             allow_push=False,
                             allow_pop=False,
                             default_value=0,
                             always_signal_changed=False,
                             boring=True)


def create_and_run_context(*args, runtime_overrides=None):