예제 #1
0
def test_async_add_opp_job_schedule_callback():
    """Test that we schedule coroutines and add jobs to the job pool."""
    opp = MagicMock()
    job = MagicMock()

    ha.OpenPeerPower.async_add_opp_job(opp, ha.OppJob(ha.callback(job)))
    assert len(opp.loop.call_soon.mock_calls) == 1
    assert len(opp.loop.create_task.mock_calls) == 0
    assert len(opp.add_job.mock_calls) == 0
예제 #2
0
def test_async_add_opp_job_schedule_partial_callback():
    """Test that we schedule partial coros and add jobs to the job pool."""
    opp = MagicMock()
    job = MagicMock()
    partial = functools.partial(ha.callback(job))

    ha.OpenPeerPower.async_add_opp_job(opp, ha.OppJob(partial))
    assert len(opp.loop.call_soon.mock_calls) == 1
    assert len(opp.loop.create_task.mock_calls) == 0
    assert len(opp.add_job.mock_calls) == 0
예제 #3
0
def test_async_run_opp_job_calls_callback():
    """Test that the callback annotation is respected."""
    opp = MagicMock()
    calls = []

    def job():
        calls.append(1)

    ha.OpenPeerPower.async_run_opp_job(opp, ha.OppJob(ha.callback(job)))
    assert len(calls) == 1
    assert len(opp.async_add_job.mock_calls) == 0
예제 #4
0
    async def async_added_to_opp(self):
        """Subscribe to children and template state changes."""
        @callback
        def _async_on_dependency_update(event):
            """Update ha state when dependencies update."""
            self.async_set_context(event.context)
            self.async_schedule_update_op_state(True)

        @callback
        def _async_on_template_update(event, updates):
            """Update ha state when dependencies update."""
            result = updates.pop().result

            if isinstance(result, TemplateError):
                self._state_template_result = None
            else:
                self._state_template_result = result

            if event:
                self.async_set_context(event.context)

            self.async_schedule_update_op_state(True)

        if self._state_template is not None:
            result = async_track_template_result(
                self.opp,
                [TrackTemplate(self._state_template, None)],
                _async_on_template_update,
            )
            self.opp.bus.async_listen_once(
                EVENT_OPENPEERPOWER_START,
                callback(lambda _: result.async_refresh()))

            self.async_on_remove(result.async_remove)

        depend = copy(self._children)
        for entity in self._attrs.values():
            depend.append(entity[0])

        self.async_on_remove(
            self.opp.helpers.event.async_track_state_change_event(
                list(set(depend)), _async_on_dependency_update))
예제 #5
0
async def test_state_triggers(opp):
    """Test sensor with state triggers."""
    opp.states.async_set("sensor.test_monitored", STATE_OFF)

    config = {
        "binary_sensor": {
            "name":
            "Test_Binary",
            "platform":
            "bayesian",
            "observations": [
                {
                    "platform": "state",
                    "entity_id": "sensor.test_monitored",
                    "to_state": "off",
                    "prob_given_true": 999.9,
                    "prob_given_false": 999.4,
                },
            ],
            "prior":
            0.2,
            "probability_threshold":
            0.32,
        }
    }
    await async_setup_component(opp, "binary_sensor", config)
    await opp.async_block_till_done()

    assert opp.states.get("binary_sensor.test_binary").state == STATE_OFF

    events = []
    opp.helpers.event.async_track_state_change_event(
        "binary_sensor.test_binary",
        callback(lambda event: events.append(event)))

    context = Context()
    opp.states.async_set("sensor.test_monitored", STATE_ON, context=context)
    await opp.async_block_till_done()
    await opp.async_block_till_done()

    assert events[0].context == context
예제 #6
0
async def test_master_state_with_template(opp):
    """Test the state_template option."""
    opp.states.async_set("input_boolean.test", STATE_OFF)
    opp.states.async_set("media_player.mock1", STATE_OFF)

    templ = (
        '{% if states.input_boolean.test.state == "off" %}on'
        "{% else %}{{ states.media_player.mock1.state }}{% endif %}"
    )

    await async_setup_component(
        opp,
        "media_player",
        {
            "media_player": {
                "platform": "universal",
                "name": "tv",
                "state_template": templ,
            }
        },
    )

    await opp.async_block_till_done()
    assert len(opp.states.async_all()) == 3
    await opp.async_start()

    await opp.async_block_till_done()
    assert opp.states.get("media_player.tv").state == STATE_ON

    events = []

    opp.helpers.event.async_track_state_change_event(
        "media_player.tv", callback(lambda event: events.append(event))
    )

    context = Context()
    opp.states.async_set("input_boolean.test", STATE_ON, context=context)
    await opp.async_block_till_done()

    assert opp.states.get("media_player.tv").state == STATE_OFF
    assert events[0].context == context
예제 #7
0
def catch_log_exception(
        func: Callable[..., Any], format_err: Callable[..., Any],
        *args: Any) -> Callable[..., None] | Callable[..., Awaitable[None]]:
    """Decorate a callback to catch and log exceptions."""

    # Check for partials to properly determine if coroutine function
    check_func = func
    while isinstance(check_func, partial):
        check_func = check_func.func

    wrapper_func: Callable[..., None] | Callable[..., Awaitable[None]]
    if asyncio.iscoroutinefunction(check_func):
        async_func = cast(Callable[..., Awaitable[None]], func)

        @wraps(async_func)
        async def async_wrapper(*args: Any) -> None:
            """Catch and log exception."""
            try:
                await async_func(*args)
            except Exception:  # pylint: disable=broad-except
                log_exception(format_err, *args)

        wrapper_func = async_wrapper

    else:

        @wraps(func)
        def wrapper(*args: Any) -> None:
            """Catch and log exception."""
            try:
                func(*args)
            except Exception:  # pylint: disable=broad-except
                log_exception(format_err, *args)

        if is_callback(check_func):
            wrapper = callback(wrapper)

        wrapper_func = wrapper
    return wrapper_func
예제 #8
0
async def async_setup(opp: OpenPeerPower, config: ConfigType) -> bool:
    """Set up an input select."""
    component = EntityComponent(_LOGGER, DOMAIN, opp)
    id_manager = collection.IDManager()

    yaml_collection = collection.YamlCollection(
        logging.getLogger(f"{__name__}.yaml_collection"), id_manager)
    collection.sync_entity_lifecycle(opp, DOMAIN, DOMAIN, component,
                                     yaml_collection, InputSelect.from_yaml)

    storage_collection = InputSelectStorageCollection(
        Store(opp, STORAGE_VERSION, STORAGE_KEY),
        logging.getLogger(f"{__name__}.storage_collection"),
        id_manager,
    )
    collection.sync_entity_lifecycle(opp, DOMAIN, DOMAIN, component,
                                     storage_collection, InputSelect)

    await yaml_collection.async_load([{
        CONF_ID: id_,
        **cfg
    } for id_, cfg in config.get(DOMAIN, {}).items()])
    await storage_collection.async_load()

    collection.StorageCollectionWebsocket(storage_collection, DOMAIN, DOMAIN,
                                          CREATE_FIELDS,
                                          UPDATE_FIELDS).async_setup(opp)

    async def reload_service_handler(service_call: ServiceCall) -> None:
        """Reload yaml entities."""
        conf = await component.async_prepare_reload(skip_reset=True)
        if conf is None:
            conf = {DOMAIN: {}}
        await yaml_collection.async_load([{
            CONF_ID: id_,
            **cfg
        } for id_, cfg in conf.get(DOMAIN, {}).items()])

    openpeerpower.helpers.service.async_register_admin_service(
        opp,
        DOMAIN,
        SERVICE_RELOAD,
        reload_service_handler,
        schema=RELOAD_SERVICE_SCHEMA,
    )

    component.async_register_entity_service(
        SERVICE_SELECT_OPTION,
        {vol.Required(ATTR_OPTION): cv.string},
        "async_select_option",
    )

    component.async_register_entity_service(
        SERVICE_SELECT_NEXT,
        {vol.Optional(ATTR_CYCLE, default=True): bool},
        "async_next",
    )

    component.async_register_entity_service(
        SERVICE_SELECT_PREVIOUS,
        {vol.Optional(ATTR_CYCLE, default=True): bool},
        "async_previous",
    )

    component.async_register_entity_service(
        SERVICE_SELECT_FIRST,
        {},
        callback(lambda entity, call: entity.async_select_index(0)),
    )

    component.async_register_entity_service(
        SERVICE_SELECT_LAST,
        {},
        callback(lambda entity, call: entity.async_select_index(-1)),
    )

    component.async_register_entity_service(
        SERVICE_SET_OPTIONS,
        {
            vol.Required(ATTR_OPTIONS):
            vol.All(cv.ensure_list, vol.Length(min=1), [cv.string])
        },
        "async_set_options",
    )

    return True
예제 #9
0
 async def _subscribe_topics(sub_state, topics):
     # Optionally mark message handlers as callback
     for topic in topics.values():
         if "msg_callback" in topic and "event_loop_safe" in topic:
             topic["msg_callback"] = callback(topic["msg_callback"])
     return await async_subscribe_topics(opp, sub_state, topics)