Compare commits

...

4 Commits

Author SHA1 Message Date
G Johansson
dc2beeb968 string 2025-10-04 08:19:49 +00:00
G Johansson
087aed5a7c Fix 2025-10-03 17:28:07 +00:00
G Johansson
beddc028b0 Mods 2025-10-03 17:20:37 +00:00
G Johansson
0f559ce644 Raise repairs on platform setup for command_line 2025-10-03 15:41:08 +00:00
12 changed files with 116 additions and 18 deletions

View File

@@ -5,7 +5,10 @@ from __future__ import annotations
import asyncio
from datetime import datetime, timedelta
from homeassistant.components.binary_sensor import BinarySensorEntity
from homeassistant.components.binary_sensor import (
DOMAIN as BINARY_SENSOR_DOMAIN,
BinarySensorEntity,
)
from homeassistant.const import (
CONF_COMMAND,
CONF_NAME,
@@ -27,6 +30,7 @@ from homeassistant.util import dt as dt_util
from .const import CONF_COMMAND_TIMEOUT, LOGGER, TRIGGER_ENTITY_OPTIONS
from .sensor import CommandSensorData
from .utils import create_platform_yaml_not_supported_issue
DEFAULT_NAME = "Binary Command Sensor"
DEFAULT_PAYLOAD_ON = "ON"
@@ -43,6 +47,7 @@ async def async_setup_platform(
) -> None:
"""Set up the Command line Binary Sensor."""
if not discovery_info:
create_platform_yaml_not_supported_issue(hass, BINARY_SENSOR_DOMAIN)
return
binary_sensor_config = discovery_info

View File

@@ -6,7 +6,7 @@ import asyncio
from datetime import datetime, timedelta
from typing import TYPE_CHECKING, Any
from homeassistant.components.cover import CoverEntity
from homeassistant.components.cover import DOMAIN as COVER_DOMAIN, CoverEntity
from homeassistant.const import (
CONF_COMMAND_CLOSE,
CONF_COMMAND_OPEN,
@@ -28,7 +28,11 @@ from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
from homeassistant.util import dt as dt_util, slugify
from .const import CONF_COMMAND_TIMEOUT, LOGGER, TRIGGER_ENTITY_OPTIONS
from .utils import async_call_shell_with_timeout, async_check_output_or_log
from .utils import (
async_call_shell_with_timeout,
async_check_output_or_log,
create_platform_yaml_not_supported_issue,
)
SCAN_INTERVAL = timedelta(seconds=15)
@@ -41,6 +45,7 @@ async def async_setup_platform(
) -> None:
"""Set up cover controlled by shell commands."""
if not discovery_info:
create_platform_yaml_not_supported_issue(hass, COVER_DOMAIN)
return
covers = []

View File

@@ -6,13 +6,17 @@ import logging
import subprocess
from typing import Any
from homeassistant.components.notify import BaseNotificationService
from homeassistant.components.notify import (
DOMAIN as NOTIFY_DOMAIN,
BaseNotificationService,
)
from homeassistant.const import CONF_COMMAND
from homeassistant.core import HomeAssistant
from homeassistant.helpers.issue_registry import IssueSeverity, create_issue
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
from homeassistant.util.process import kill_subprocess
from .const import CONF_COMMAND_TIMEOUT, LOGGER
from .const import CONF_COMMAND_TIMEOUT, DOMAIN, LOGGER
from .utils import render_template_args
_LOGGER = logging.getLogger(__name__)
@@ -25,6 +29,16 @@ def get_service(
) -> CommandLineNotificationService | None:
"""Get the Command Line notification service."""
if not discovery_info:
create_issue(
hass,
DOMAIN,
"notify_platform_yaml_not_supported",
is_fixable=False,
severity=IssueSeverity.WARNING,
translation_key="platform_yaml_not_supported",
translation_placeholders={"platform": NOTIFY_DOMAIN},
learn_more_url="https://www.home-assistant.io/integrations/command_line/",
)
return None
notify_config = discovery_info

View File

@@ -10,6 +10,7 @@ from typing import Any
from jsonpath import jsonpath
from homeassistant.components.sensor import DOMAIN as SENSOR_DOMAIN
from homeassistant.const import (
CONF_COMMAND,
CONF_NAME,
@@ -34,7 +35,11 @@ from .const import (
LOGGER,
TRIGGER_ENTITY_OPTIONS,
)
from .utils import async_check_output_or_log, render_template_args
from .utils import (
async_check_output_or_log,
create_platform_yaml_not_supported_issue,
render_template_args,
)
DEFAULT_NAME = "Command Sensor"
@@ -49,6 +54,7 @@ async def async_setup_platform(
) -> None:
"""Set up the Command Sensor."""
if not discovery_info:
create_platform_yaml_not_supported_issue(hass, SENSOR_DOMAIN)
return
sensor_config = discovery_info

View File

@@ -4,5 +4,11 @@
"name": "[%key:common::action::reload%]",
"description": "Reloads command line configuration from the YAML-configuration."
}
},
"issues": {
"platform_yaml_not_supported": {
"title": "Platform YAML is not supported in Command Line",
"description": "Platform YAML setup is not supported.\nChange from configuring it in the `sensor:` key to using the `command_line:` key directly in configuration.yaml.\nTo see the detailed documentation, select Learn more."
}
}
}

View File

@@ -6,7 +6,11 @@ import asyncio
from datetime import datetime, timedelta
from typing import TYPE_CHECKING, Any
from homeassistant.components.switch import ENTITY_ID_FORMAT, SwitchEntity
from homeassistant.components.switch import (
DOMAIN as SWITCH_DOMAIN,
ENTITY_ID_FORMAT,
SwitchEntity,
)
from homeassistant.const import (
CONF_COMMAND_OFF,
CONF_COMMAND_ON,
@@ -27,7 +31,11 @@ from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
from homeassistant.util import dt as dt_util, slugify
from .const import CONF_COMMAND_TIMEOUT, LOGGER, TRIGGER_ENTITY_OPTIONS
from .utils import async_call_shell_with_timeout, async_check_output_or_log
from .utils import (
async_call_shell_with_timeout,
async_check_output_or_log,
create_platform_yaml_not_supported_issue,
)
SCAN_INTERVAL = timedelta(seconds=30)
@@ -40,6 +48,7 @@ async def async_setup_platform(
) -> None:
"""Find and return switches controlled by shell commands."""
if not discovery_info:
create_platform_yaml_not_supported_issue(hass, SWITCH_DOMAIN)
return
switches = []

View File

@@ -6,9 +6,10 @@ import asyncio
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import TemplateError
from homeassistant.helpers.issue_registry import IssueSeverity, async_create_issue
from homeassistant.helpers.template import Template
from .const import LOGGER
from .const import DOMAIN, LOGGER
_EXEC_FAILED_CODE = 127
@@ -93,3 +94,19 @@ def render_template_args(hass: HomeAssistant, command: str) -> str | None:
LOGGER.debug("Running command: %s", command)
return command
def create_platform_yaml_not_supported_issue(
hass: HomeAssistant, platform_domain: str
) -> None:
"""Create an issue when platform yaml is used."""
async_create_issue(
hass,
DOMAIN,
f"{platform_domain}_platform_yaml_not_supported",
is_fixable=False,
severity=IssueSeverity.WARNING,
translation_key="platform_yaml_not_supported",
translation_placeholders={"platform": platform_domain},
learn_more_url="https://www.home-assistant.io/integrations/command_line/",
)

View File

@@ -11,6 +11,7 @@ from freezegun.api import FrozenDateTimeFactory
import pytest
from homeassistant import setup
from homeassistant.components.binary_sensor import DOMAIN as BINARY_SENSOR_DOMAIN
from homeassistant.components.command_line.binary_sensor import CommandBinarySensor
from homeassistant.components.command_line.const import DOMAIN
from homeassistant.components.homeassistant import (
@@ -19,7 +20,7 @@ from homeassistant.components.homeassistant import (
)
from homeassistant.const import ATTR_ENTITY_ID, STATE_OFF, STATE_ON, STATE_UNAVAILABLE
from homeassistant.core import HomeAssistant
from homeassistant.helpers import entity_registry as er
from homeassistant.helpers import entity_registry as er, issue_registry as ir
from homeassistant.util import dt as dt_util
from . import mock_asyncio_subprocess_run
@@ -56,7 +57,9 @@ async def test_setup_integration_yaml(
assert entity_state.name == "Test"
async def test_setup_platform_yaml(hass: HomeAssistant) -> None:
async def test_setup_platform_yaml(
hass: HomeAssistant, issue_registry: ir.IssueRegistry
) -> None:
"""Test setting up the platform with platform yaml."""
await setup.async_setup_component(
hass,
@@ -73,6 +76,13 @@ async def test_setup_platform_yaml(hass: HomeAssistant) -> None:
await hass.async_block_till_done()
assert len(hass.states.async_all()) == 0
issue = issue_registry.async_get_issue(
DOMAIN, "binary_sensor_platform_yaml_not_supported"
)
assert issue is not None
assert issue.severity == ir.IssueSeverity.WARNING
assert issue.translation_placeholders == {"platform": BINARY_SENSOR_DOMAIN}
@pytest.mark.parametrize(
"get_config",

View File

@@ -31,7 +31,7 @@ from homeassistant.const import (
STATE_UNAVAILABLE,
)
from homeassistant.core import HomeAssistant
from homeassistant.helpers import entity_registry as er
from homeassistant.helpers import entity_registry as er, issue_registry as ir
from homeassistant.util import dt as dt_util
from . import mock_asyncio_subprocess_run
@@ -39,7 +39,9 @@ from . import mock_asyncio_subprocess_run
from tests.common import async_fire_time_changed
async def test_setup_platform_yaml(hass: HomeAssistant) -> None:
async def test_setup_platform_yaml(
hass: HomeAssistant, issue_registry: ir.IssueRegistry
) -> None:
"""Test setting up the platform with platform yaml."""
await setup.async_setup_component(
hass,
@@ -55,6 +57,10 @@ async def test_setup_platform_yaml(hass: HomeAssistant) -> None:
)
await hass.async_block_till_done()
assert len(hass.states.async_all()) == 0
issue = issue_registry.async_get_issue(DOMAIN, "cover_platform_yaml_not_supported")
assert issue is not None
assert issue.severity == ir.IssueSeverity.WARNING
assert issue.translation_placeholders == {"platform": COVER_DOMAIN}
async def test_no_poll_when_cover_has_no_command_state(hass: HomeAssistant) -> None:

View File

@@ -14,9 +14,12 @@ from homeassistant import setup
from homeassistant.components.command_line import DOMAIN
from homeassistant.components.notify import DOMAIN as NOTIFY_DOMAIN
from homeassistant.core import HomeAssistant
from homeassistant.helpers import issue_registry as ir
async def test_setup_platform_yaml(hass: HomeAssistant) -> None:
async def test_setup_platform_yaml(
hass: HomeAssistant, issue_registry: ir.IssueRegistry
) -> None:
"""Test setting up the platform with platform yaml."""
await setup.async_setup_component(
hass,
@@ -32,6 +35,10 @@ async def test_setup_platform_yaml(hass: HomeAssistant) -> None:
)
await hass.async_block_till_done()
assert len(hass.states.async_all()) == 0
issue = issue_registry.async_get_issue(DOMAIN, "notify_platform_yaml_not_supported")
assert issue is not None
assert issue.severity == ir.IssueSeverity.WARNING
assert issue.translation_placeholders == {"platform": NOTIFY_DOMAIN}
@pytest.mark.parametrize(

View File

@@ -17,9 +17,10 @@ from homeassistant.components.homeassistant import (
DOMAIN as HA_DOMAIN,
SERVICE_UPDATE_ENTITY,
)
from homeassistant.components.sensor import DOMAIN as SENSOR_DOMAIN
from homeassistant.const import ATTR_ENTITY_ID, STATE_UNAVAILABLE, STATE_UNKNOWN
from homeassistant.core import HomeAssistant
from homeassistant.helpers import entity_registry as er
from homeassistant.helpers import entity_registry as er, issue_registry as ir
from homeassistant.util import dt as dt_util
from . import mock_asyncio_subprocess_run
@@ -27,7 +28,9 @@ from . import mock_asyncio_subprocess_run
from tests.common import async_fire_time_changed
async def test_setup_platform_yaml(hass: HomeAssistant) -> None:
async def test_setup_platform_yaml(
hass: HomeAssistant, issue_registry: ir.IssueRegistry
) -> None:
"""Test setting up the platform with platform yaml."""
await setup.async_setup_component(
hass,
@@ -43,6 +46,10 @@ async def test_setup_platform_yaml(hass: HomeAssistant) -> None:
)
await hass.async_block_till_done()
assert len(hass.states.async_all()) == 0
issue = issue_registry.async_get_issue(DOMAIN, "sensor_platform_yaml_not_supported")
assert issue is not None
assert issue.severity == ir.IssueSeverity.WARNING
assert issue.translation_placeholders == {"platform": SENSOR_DOMAIN}
@pytest.mark.parametrize(

View File

@@ -29,7 +29,7 @@ from homeassistant.const import (
STATE_UNAVAILABLE,
)
from homeassistant.core import HomeAssistant
from homeassistant.helpers import entity_registry as er
from homeassistant.helpers import entity_registry as er, issue_registry as ir
from homeassistant.util import dt as dt_util
from . import mock_asyncio_subprocess_run
@@ -37,7 +37,9 @@ from . import mock_asyncio_subprocess_run
from tests.common import async_fire_time_changed
async def test_setup_platform_yaml(hass: HomeAssistant) -> None:
async def test_setup_platform_yaml(
hass: HomeAssistant, issue_registry: ir.IssueRegistry
) -> None:
"""Test setting up the platform with platform yaml."""
await setup.async_setup_component(
hass,
@@ -53,6 +55,10 @@ async def test_setup_platform_yaml(hass: HomeAssistant) -> None:
)
await hass.async_block_till_done()
assert len(hass.states.async_all()) == 0
issue = issue_registry.async_get_issue(DOMAIN, "switch_platform_yaml_not_supported")
assert issue is not None
assert issue.severity == ir.IssueSeverity.WARNING
assert issue.translation_placeholders == {"platform": SWITCH_DOMAIN}
async def test_state_integration_yaml(hass: HomeAssistant) -> None: