def test_integration_properties(hass):
    """Test integration properties."""
    integration = loader.Integration(
        hass,
        "homeassistant.components.hue",
        None,
        {
            "name": "Philips Hue",
            "domain": "hue",
            "dependencies": ["test-dep"],
            "requirements": ["test-req==1.0.0"],
        },
    )
    assert integration.name == "Philips Hue"
    assert integration.domain == "hue"
    assert integration.dependencies == ["test-dep"]
    assert integration.requirements == ["test-req==1.0.0"]
    assert integration.is_built_in is True

    integration = loader.Integration(
        hass,
        "custom_components.hue",
        None,
        {
            "name": "Philips Hue",
            "domain": "hue",
            "dependencies": ["test-dep"],
            "requirements": ["test-req==1.0.0"],
        },
    )
    assert integration.is_built_in is False
async def test_custom_integration_missing_version(hass, caplog):
    """Test that we log a warning when custom integrations are missing a version."""
    test_integration_1 = loader.Integration(
        hass, "custom_components.test1", None, {"domain": "test1"}
    )
    test_integration_2 = loader.Integration(
        hass,
        "custom_components.test2",
        None,
        loader.manifest_from_legacy_module("test2", "custom_components.test2"),
    )

    with patch("homeassistant.loader.async_get_custom_components") as mock_get:
        mock_get.return_value = {
            "test1": test_integration_1,
            "test2": test_integration_2,
        }

        await loader.async_get_integration(hass, "test1")
        assert (
            "No 'version' key in the manifest file for custom integration 'test1'."
            in caplog.text
        )

        await loader.async_get_integration(hass, "test2")
        assert (
            "No 'version' key in the manifest file for custom integration 'test2'."
            in caplog.text
        )
Beispiel #3
0
async def test_custom_integration_version_not_valid(hass, caplog):
    """Test that we log a warning when custom integrations have a invalid version."""
    test_integration1 = loader.Integration(
        hass, "custom_components.test", None, {"domain": "test1", "version": "test"}
    )
    test_integration2 = loader.Integration(
        hass, "custom_components.test", None, {"domain": "test2"}
    )

    with patch("homeassistant.loader.async_get_custom_components") as mock_get:
        mock_get.return_value = {"test1": test_integration1, "test2": test_integration2}

        with pytest.raises(loader.IntegrationNotFound):
            await loader.async_get_integration(hass, "test1")
        assert (
            "The custom integration 'test1' does not have a valid version key (test) in the manifest file and was blocked from loading."
            in caplog.text
        )

        with pytest.raises(loader.IntegrationNotFound):
            await loader.async_get_integration(hass, "test2")
        assert (
            "The custom integration 'test2' does not have a valid version key (None) in the manifest file and was blocked from loading."
            in caplog.text
        )
Beispiel #4
0
def _get_test_integration_with_usb_matcher(hass, name, config_flow):
    """Return a generated test integration with a usb matcher."""
    return loader.Integration(
        hass,
        f"homeassistant.components.{name}",
        None,
        {
            "name": name,
            "domain": name,
            "config_flow": config_flow,
            "dependencies": [],
            "requirements": [],
            "usb": [
                {
                    "vid": "10C4",
                    "pid": "EA60",
                    "known_devices": ["slae.sh cc2652rb stick"],
                },
                {"vid": "1CF1", "pid": "0030", "known_devices": ["Conbee II"]},
                {
                    "vid": "1A86",
                    "pid": "7523",
                    "known_devices": ["Electrolama zig-a-zig-ah"],
                },
                {"vid": "10C4", "pid": "8A2A", "known_devices": ["Nortek HUSBZB-1"]},
            ],
        },
    )
Beispiel #5
0
def _get_test_integration_with_zeroconf_matcher(hass, name, config_flow):
    """Return a generated test integration with a zeroconf matcher."""
    return loader.Integration(
        hass,
        f"homeassistant.components.{name}",
        None,
        {
            "name": name,
            "domain": name,
            "config_flow": config_flow,
            "dependencies": [],
            "requirements": [],
            "zeroconf": [{
                "type": f"_{name}._tcp.local.",
                "name": f"{name}*"
            }],
            "homekit": {
                "models": [name]
            },
            "ssdp": [{
                "manufacturer": name,
                "modelName": name
            }],
        },
    )
Beispiel #6
0
async def test_service_description(hass):
    """Test service description defined in doc_string."""

    await setup_script(
        hass,
        None,
        dt(2020, 7, 1, 11, 59, 59, 999999),
        """
@service
def func_no_doc_string(param1=None):
    pass

@service
def func_simple_doc_string(param2=None, param3=None):
    \"\"\"This is func2_simple_doc_string.\"\"\"
    pass

@service
def func_yaml_doc_string(param2=None, param3=None):
    \"\"\"yaml
description: This is func_yaml_doc_string.
fields:
  param1:
    description: first argument
    example: 12
  param2:
    description: second argument
    example: 34
\"\"\"
    pass
""",
    )

    integration = loader.Integration(
        hass,
        "custom_components.pyscript",
        pathlib.Path("custom_components/pyscript"),
        {"name": "pyscript", "dependencies": [], "requirements": [], "domain": "automation"},
    )

    with patch(
        "homeassistant.loader.async_get_custom_components", return_value={"pyscript": integration},
    ):
        descriptions = (await async_get_all_descriptions(hass))[DOMAIN]

    assert descriptions["func_no_doc_string"]["description"] == "pyscript function func_no_doc_string()"
    assert descriptions["func_no_doc_string"]["fields"] == {"param1": {"description": "argument param1"}}

    assert descriptions["func_simple_doc_string"]["description"] == "This is func2_simple_doc_string."
    assert descriptions["func_simple_doc_string"]["fields"] == {
        "param2": {"description": "argument param2"},
        "param3": {"description": "argument param3"},
    }

    assert descriptions["func_yaml_doc_string"]["description"] == "This is func_yaml_doc_string."
    assert descriptions["func_yaml_doc_string"]["fields"] == {
        "param1": {"description": "first argument", "example": "12"},
        "param2": {"description": "second argument", "example": "34"},
    }
Beispiel #7
0
def mock_integration(hass, module):
    """Mock an integration."""
    integration = loader.Integration(
        hass, f"homeassistant.components.{module.DOMAIN}", None, module.mock_manifest(),
    )

    _LOGGER.info("Adding mock integration: %s", module.DOMAIN)
    hass.data.setdefault(loader.DATA_INTEGRATIONS, {})[module.DOMAIN] = integration
    hass.data.setdefault(loader.DATA_COMPONENTS, {})[module.DOMAIN] = module
Beispiel #8
0
def _get_test_integration(hass, name, config_flow):
    """Return a generated test integration."""
    return loader.Integration(
        hass, "homeassistant.components.{}".format(name), None, {
            'name': name,
            'domain': name,
            'config_flow': config_flow,
            'dependencies': [],
            'requirements': []})
Beispiel #9
0
async def setup_script(hass, notify_q, now, source):
    """Initialize and load the given pyscript."""
    scripts = [
        "/some/config/dir/pyscripts/hello.py",
    ]
    integration = loader.Integration(
        hass,
        "config.custom_components.pyscript",
        pathlib.Path("config/custom_components/pyscript"),
        {
            "name": "pyscript",
            "dependencies": [],
            "requirements": [],
            "domain": "automation",
        },
    )

    with patch(
            "homeassistant.loader.async_get_integration",
            return_value=integration,
    ), patch("config.custom_components.pyscript.os.path.isdir",
             return_value=True), patch(
                 "config.custom_components.pyscript.glob.iglob",
                 return_value=scripts), patch(
                     "config.custom_components.pyscript.open",
                     mock_open(read_data=source),
                     create=True,
                 ), patch("config.custom_components.pyscript.trigger.dt_now",
                          return_value=now):
        assert await async_setup_component(hass, "pyscript", {})

    #
    # I'm not sure how to run the mock all the time, so just force the dt_now()
    # trigger function to return the given list of times in now.
    #
    def return_next_time():
        nonlocal now
        if isinstance(now, list):
            if len(now) > 1:
                return now.pop(0)
            return now[0]
        return now

    trigger.__dict__["dt_now"] = return_next_time

    if notify_q:

        async def state_changed(event):
            var_name = event.data["entity_id"]
            if var_name != "pyscript.done":
                return
            value = event.data["new_state"].state
            await notify_q.put(value)

        hass.bus.async_listen(EVENT_STATE_CHANGED, state_changed)
Beispiel #10
0
async def test_init_custom_integration(hass):
    """Test initializing flow for custom integration."""
    integration = loader.Integration(hass, 'custom_components.hue', None, {
        'name': 'Hue',
        'dependencies': [],
        'requirements': [],
        'domain': 'hue',
    })
    with pytest.raises(data_entry_flow.UnknownHandler):
        with patch('homeassistant.loader.async_get_integration',
                   return_value=mock_coro(integration)):
            await hass.config_entries.flow.async_init('bla')
Beispiel #11
0
def test_integration_properties(hass):
    """Test integration properties."""
    integration = loader.Integration(
        hass, 'homeassistant.components.hue', None, {
            'name': 'Philips Hue',
            'domain': 'hue',
            'dependencies': ['test-dep'],
            'requirements': ['test-req==1.0.0'],
        })
    assert integration.name == "Philips Hue"
    assert integration.domain == 'hue'
    assert integration.dependencies == ['test-dep']
    assert integration.requirements == ['test-req==1.0.0']
def _get_test_integration(hass, name, config_flow):
    """Return a generated test integration."""
    return loader.Integration(
        hass,
        f"homeassistant.components.{name}",
        None,
        {
            "name": name,
            "domain": name,
            "config_flow": config_flow,
            "dependencies": [],
            "requirements": [],
        },
    )
async def test_custom_integration_version_not_valid(hass, caplog):
    """Test that we log a warning when custom integrations have a invalid version."""
    test_integration = loader.Integration(
        hass, "custom_components.test", None, {"domain": "test", "version": "test"}
    )

    with patch("homeassistant.loader.async_get_custom_components") as mock_get:
        mock_get.return_value = {"test": test_integration}

        await loader.async_get_integration(hass, "test")
        assert (
            "'test' is not a valid version for custom integration 'test'."
            in caplog.text
        )
Beispiel #14
0
async def test_custom_integration_missing_version(hass, caplog):
    """Test trying to load a custom integration without a version twice does not deadlock."""
    test_integration_1 = loader.Integration(
        hass, "custom_components.test1", None, {"domain": "test1"}
    )
    with patch("homeassistant.loader.async_get_custom_components") as mock_get:
        mock_get.return_value = {
            "test1": test_integration_1,
        }

        with pytest.raises(loader.IntegrationNotFound):
            await loader.async_get_integration(hass, "test1")

        with pytest.raises(loader.IntegrationNotFound):
            await loader.async_get_integration(hass, "test1")
async def test_loggers(hass):
    """Test we can fetch the loggers from the integration."""
    name = "dummy"
    integration = loader.Integration(
        hass,
        f"homeassistant.components.{name}",
        None,
        {
            "name": name,
            "domain": name,
            "config_flow": True,
            "dependencies": [],
            "requirements": [],
            "loggers": ["name1", "name2"],
        },
    )
    assert integration.loggers == ["name1", "name2"]
Beispiel #16
0
def _get_test_integration_with_bluetooth_matcher(hass, name, config_flow):
    """Return a generated test integration with a bluetooth matcher."""
    return loader.Integration(
        hass,
        f"homeassistant.components.{name}",
        None,
        {
            "name": name,
            "domain": name,
            "config_flow": config_flow,
            "bluetooth": [
                {
                    "local_name": "Prodigio_*",
                },
            ],
        },
    )
Beispiel #17
0
def _get_test_integration(hass, name, config_flow):
    """Return a generated test integration."""
    return loader.Integration(
        hass,
        f"homeassistant.components.{name}",
        None,
        {
            "name": name,
            "domain": name,
            "config_flow": config_flow,
            "dependencies": [],
            "requirements": [],
            "zeroconf": [f"_{name}._tcp.local."],
            "homekit": {"models": [name]},
            "ssdp": [{"manufacturer": name, "modelName": name}],
            "mqtt": [f"{name}/discovery"],
        },
    )
async def test_init_custom_integration(hass):
    """Test initializing flow for custom integration."""
    integration = loader.Integration(
        hass,
        "custom_components.hue",
        None,
        {
            "name": "Hue",
            "dependencies": [],
            "requirements": [],
            "domain": "hue"
        },
    )
    with pytest.raises(data_entry_flow.UnknownHandler):
        with patch(
                "homeassistant.loader.async_get_integration",
                return_value=mock_coro(integration),
        ):
            await hass.config_entries.flow.async_init("bla")
Beispiel #19
0
def mock_integration(hass, module):
    """Mock an integration."""
    integration = loader.Integration(
        hass, f"homeassistant.components.{module.DOMAIN}", None,
        module.mock_manifest())

    def mock_import_platform(platform_name):
        raise ImportError(
            f"Mocked unable to import platform '{platform_name}'",
            name=f"{integration.pkg_path}.{platform_name}",
        )

    integration._import_platform = mock_import_platform

    _LOGGER.info("Adding mock integration: %s", module.DOMAIN)
    hass.data.setdefault(loader.DATA_INTEGRATIONS,
                         {})[module.DOMAIN] = integration
    hass.data.setdefault(loader.DATA_COMPONENTS, {})[module.DOMAIN] = module

    return integration
Beispiel #20
0
def _get_test_integration_with_dhcp_matcher(hass, name, config_flow):
    """Return a generated test integration with a dhcp matcher."""
    return loader.Integration(
        hass,
        f"homeassistant.components.{name}",
        None,
        {
            "name": name,
            "domain": name,
            "config_flow": config_flow,
            "dependencies": [],
            "requirements": [],
            "zeroconf": [],
            "dhcp": [
                {"hostname": "tesla_*", "macaddress": "4CFCAA*"},
                {"hostname": "tesla_*", "macaddress": "044EAF*"},
                {"hostname": "tesla_*", "macaddress": "98ED5C*"},
            ],
            "homekit": {"models": [name]},
            "ssdp": [{"manufacturer": name, "modelName": name}],
        },
    )
Beispiel #21
0
async def test_setup_fails_on_no_dir(hass, caplog):
    """Test we fail setup when no dir found."""
    integration = loader.Integration(
        hass,
        "config.custom_components.pyscript",
        pathlib.Path("config/custom_components/pyscript"),
        {
            "name": "pyscript",
            "dependencies": [],
            "requirements": [],
            "domain": "automation",
        },
    )

    with patch(
            "homeassistant.loader.async_get_integration",
            return_value=integration,
    ), patch("config.custom_components.pyscript.os.path.isdir",
             return_value=False):
        res = await async_setup_component(hass, "pyscript", {})

    assert not res
    assert "Folder pyscript not found in configuration folder" in caplog.text
Beispiel #22
0
def mock_integration(hass, module, built_in=True):
    """Mock an integration."""
    integration = loader.Integration(
        hass,
        f"{loader.PACKAGE_BUILTIN}.{module.DOMAIN}"
        if built_in else f"{loader.PACKAGE_CUSTOM_COMPONENTS}.{module.DOMAIN}",
        None,
        module.mock_manifest(),
    )

    def mock_import_platform(platform_name):
        raise ImportError(
            f"Mocked unable to import platform '{platform_name}'",
            name=f"{integration.pkg_path}.{platform_name}",
        )

    integration._import_platform = mock_import_platform

    _LOGGER.info("Adding mock integration: %s", module.DOMAIN)
    hass.data.setdefault(loader.DATA_INTEGRATIONS,
                         {})[module.DOMAIN] = integration
    hass.data.setdefault(loader.DATA_COMPONENTS, {})[module.DOMAIN] = module

    return integration
Beispiel #23
0
def test_integration_properties(hass):
    """Test integration properties."""
    integration = loader.Integration(
        hass,
        "homeassistant.components.hue",
        None,
        {
            "name": "Philips Hue",
            "domain": "hue",
            "dependencies": ["test-dep"],
            "requirements": ["test-req==1.0.0"],
            "zeroconf": ["_hue._tcp.local."],
            "homekit": {"models": ["BSB002"]},
            "dhcp": [
                {"hostname": "tesla_*", "macaddress": "4CFCAA*"},
                {"hostname": "tesla_*", "macaddress": "044EAF*"},
                {"hostname": "tesla_*", "macaddress": "98ED5C*"},
            ],
            "ssdp": [
                {
                    "manufacturer": "Royal Philips Electronics",
                    "modelName": "Philips hue bridge 2012",
                },
                {
                    "manufacturer": "Royal Philips Electronics",
                    "modelName": "Philips hue bridge 2015",
                },
                {"manufacturer": "Signify", "modelName": "Philips hue bridge 2015"},
            ],
            "mqtt": ["hue/discovery"],
            "version": "1.0.0",
        },
    )
    assert integration.name == "Philips Hue"
    assert integration.domain == "hue"
    assert integration.homekit == {"models": ["BSB002"]}
    assert integration.zeroconf == ["_hue._tcp.local."]
    assert integration.dhcp == [
        {"hostname": "tesla_*", "macaddress": "4CFCAA*"},
        {"hostname": "tesla_*", "macaddress": "044EAF*"},
        {"hostname": "tesla_*", "macaddress": "98ED5C*"},
    ]
    assert integration.ssdp == [
        {
            "manufacturer": "Royal Philips Electronics",
            "modelName": "Philips hue bridge 2012",
        },
        {
            "manufacturer": "Royal Philips Electronics",
            "modelName": "Philips hue bridge 2015",
        },
        {"manufacturer": "Signify", "modelName": "Philips hue bridge 2015"},
    ]
    assert integration.mqtt == ["hue/discovery"]
    assert integration.dependencies == ["test-dep"]
    assert integration.requirements == ["test-req==1.0.0"]
    assert integration.is_built_in is True
    assert integration.version == "1.0.0"

    integration = loader.Integration(
        hass,
        "custom_components.hue",
        None,
        {
            "name": "Philips Hue",
            "domain": "hue",
            "dependencies": ["test-dep"],
            "requirements": ["test-req==1.0.0"],
        },
    )
    assert integration.is_built_in is False
    assert integration.homekit is None
    assert integration.zeroconf is None
    assert integration.dhcp is None
    assert integration.ssdp is None
    assert integration.mqtt is None
    assert integration.version is None

    integration = loader.Integration(
        hass,
        "custom_components.hue",
        None,
        {
            "name": "Philips Hue",
            "domain": "hue",
            "dependencies": ["test-dep"],
            "zeroconf": [{"type": "_hue._tcp.local.", "name": "hue*"}],
            "requirements": ["test-req==1.0.0"],
        },
    )
    assert integration.is_built_in is False
    assert integration.homekit is None
    assert integration.zeroconf == [{"type": "_hue._tcp.local.", "name": "hue*"}]
    assert integration.dhcp is None
    assert integration.ssdp is None
Beispiel #24
0
async def test_reload(hass, caplog):
    """Test reload."""
    notify_q = asyncio.Queue(0)
    now = dt(2020, 7, 1, 11, 59, 59, 999999)
    source0 = """
seq_num = 0

@time_trigger
def func_startup_sync():
    global seq_num

    seq_num += 1
    log.info(f"func_startup_sync setting pyscript.done = {seq_num}")
    pyscript.done = seq_num

@service
@state_trigger("pyscript.f1var1 == '1'")
def func1(var_name=None, value=None):
    global seq_num

    seq_num += 1
    log.info(f"func1 var = {var_name}, value = {value}")
    pyscript.done = [seq_num, var_name, int(value)]

"""
    source1 = """
seq_num = 10

@time_trigger
def func_startup_sync():
    global seq_num

    seq_num += 1
    log.info(f"func_startup_sync setting pyscript.done = {seq_num}")
    pyscript.done = seq_num

@service
@state_trigger("pyscript.f5var1 == '1'")
def func5(var_name=None, value=None):
    global seq_num

    seq_num += 1
    log.info(f"func5 var = {var_name}, value = {value}")
    pyscript.done = [seq_num, var_name, int(value)]

"""

    await setup_script(hass, notify_q, now, source0)

    #
    # run and reload 6 times with different sournce files to make sure seqNum
    # gets reset, autostart of func_startup_sync happens and triggers work each time
    #
    # first time: fire event to startup triggers and run func_startup_sync
    #
    hass.bus.async_fire(EVENT_HOMEASSISTANT_STARTED)
    for i in range(6):
        if i & 1:
            seq_num = 10

            assert not hass.services.has_service("pyscript", "func1")
            assert hass.services.has_service("pyscript", "reload")
            assert hass.services.has_service("pyscript", "func5")

            seq_num += 1
            assert literal_eval(await wait_until_done(notify_q)) == seq_num

            seq_num += 1
            # initialize the trigger and active variables
            hass.states.async_set("pyscript.f5var1", 0)

            # try some values that shouldn't work, then one that does
            hass.states.async_set("pyscript.f5var1", "string")
            hass.states.async_set("pyscript.f5var1", 1)
            assert literal_eval(await wait_until_done(notify_q)) == [
                seq_num,
                "pyscript.f5var1",
                1,
            ]
            assert "func5 var = pyscript.f5var1, value = 1" in caplog.text
            next_source = source0

        else:
            seq_num = 0

            assert hass.services.has_service("pyscript", "func1")
            assert hass.services.has_service("pyscript", "reload")
            assert not hass.services.has_service("pyscript", "func5")

            seq_num += 1
            assert literal_eval(await wait_until_done(notify_q)) == seq_num

            seq_num += 1
            # initialize the trigger and active variables
            hass.states.async_set("pyscript.f1var1", 0)

            # try some values that shouldn't work, then one that does
            hass.states.async_set("pyscript.f1var1", "string")
            hass.states.async_set("pyscript.f1var1", 1)
            assert literal_eval(await wait_until_done(notify_q)) == [
                seq_num,
                "pyscript.f1var1",
                1,
            ]
            assert "func1 var = pyscript.f1var1, value = 1" in caplog.text
            next_source = source1

        #
        # now reload the other source file
        #
        scripts = [
            "/some/config/dir/pyscript/hello.py",
        ]
        integration = loader.Integration(
            hass,
            "config.custom_components.pyscript",
            pathlib.Path("config/custom_components/pyscript"),
            {
                "name": "pyscript",
                "dependencies": [],
                "requirements": [],
                "domain": "automation",
            },
        )

        with patch(
                "homeassistant.loader.async_get_integration",
                return_value=integration,
        ), patch("config.custom_components.pyscript.os.path.isdir",
                 return_value=True), patch(
                     "config.custom_components.pyscript.glob.iglob",
                     return_value=scripts), patch(
                         "config.custom_components.pyscript.open",
                         mock_open(read_data=next_source),
                         create=True,
                     ), patch(
                         "config.custom_components.pyscript.trigger.dt_now",
                         return_value=now):
            await hass.services.async_call("pyscript",
                                           "reload", {},
                                           blocking=True)
Beispiel #25
0
def test_integration_properties(hass):
    """Test integration properties."""
    integration = loader.Integration(
        hass,
        "homeassistant.components.hue",
        None,
        {
            "name":
            "Philips Hue",
            "domain":
            "hue",
            "dependencies": ["test-dep"],
            "requirements": ["test-req==1.0.0"],
            "zeroconf": ["_hue._tcp.local."],
            "homekit": {
                "models": ["BSB002"]
            },
            "ssdp": [
                {
                    "manufacturer": "Royal Philips Electronics",
                    "modelName": "Philips hue bridge 2012",
                },
                {
                    "manufacturer": "Royal Philips Electronics",
                    "modelName": "Philips hue bridge 2015",
                },
                {
                    "manufacturer": "Signify",
                    "modelName": "Philips hue bridge 2015"
                },
            ],
        },
    )
    assert integration.name == "Philips Hue"
    assert integration.domain == "hue"
    assert integration.homekit == {"models": ["BSB002"]}
    assert integration.zeroconf == ["_hue._tcp.local."]
    assert integration.ssdp == [
        {
            "manufacturer": "Royal Philips Electronics",
            "modelName": "Philips hue bridge 2012",
        },
        {
            "manufacturer": "Royal Philips Electronics",
            "modelName": "Philips hue bridge 2015",
        },
        {
            "manufacturer": "Signify",
            "modelName": "Philips hue bridge 2015"
        },
    ]
    assert integration.dependencies == ["test-dep"]
    assert integration.requirements == ["test-req==1.0.0"]
    assert integration.is_built_in is True

    integration = loader.Integration(
        hass,
        "custom_components.hue",
        None,
        {
            "name": "Philips Hue",
            "domain": "hue",
            "dependencies": ["test-dep"],
            "requirements": ["test-req==1.0.0"],
        },
    )
    assert integration.is_built_in is False
    assert integration.homekit is None
    assert integration.zeroconf is None
    assert integration.ssdp is None