mirror of
https://github.com/home-assistant/core.git
synced 2025-07-19 11:17:21 +00:00
Remove deprecated yaml import from local file (#143405)
This commit is contained in:
parent
39807abc7d
commit
e9269a1d33
@ -7,38 +7,19 @@ import mimetypes
|
|||||||
|
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
from homeassistant.components.camera import (
|
from homeassistant.components.camera import Camera
|
||||||
PLATFORM_SCHEMA as CAMERA_PLATFORM_SCHEMA,
|
from homeassistant.config_entries import ConfigEntry
|
||||||
Camera,
|
|
||||||
)
|
|
||||||
from homeassistant.config_entries import SOURCE_IMPORT, ConfigEntry
|
|
||||||
from homeassistant.const import CONF_FILE_PATH, CONF_NAME
|
from homeassistant.const import CONF_FILE_PATH, CONF_NAME
|
||||||
from homeassistant.core import DOMAIN as HOMEASSISTANT_DOMAIN, HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.exceptions import ServiceValidationError
|
from homeassistant.exceptions import ServiceValidationError
|
||||||
from homeassistant.helpers import (
|
from homeassistant.helpers import config_validation as cv, entity_platform
|
||||||
config_validation as cv,
|
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
|
||||||
entity_platform,
|
|
||||||
issue_registry as ir,
|
|
||||||
)
|
|
||||||
from homeassistant.helpers.entity_platform import (
|
|
||||||
AddConfigEntryEntitiesCallback,
|
|
||||||
AddEntitiesCallback,
|
|
||||||
)
|
|
||||||
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
|
|
||||||
from homeassistant.util import slugify
|
|
||||||
|
|
||||||
from .const import DEFAULT_NAME, DOMAIN, SERVICE_UPDATE_FILE_PATH
|
from .const import SERVICE_UPDATE_FILE_PATH
|
||||||
from .util import check_file_path_access
|
from .util import check_file_path_access
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
PLATFORM_SCHEMA = CAMERA_PLATFORM_SCHEMA.extend(
|
|
||||||
{
|
|
||||||
vol.Required(CONF_FILE_PATH): cv.string,
|
|
||||||
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
async def async_setup_entry(
|
async def async_setup_entry(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
@ -67,57 +48,6 @@ async def async_setup_entry(
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
async def async_setup_platform(
|
|
||||||
hass: HomeAssistant,
|
|
||||||
config: ConfigType,
|
|
||||||
async_add_entities: AddEntitiesCallback,
|
|
||||||
discovery_info: DiscoveryInfoType | None = None,
|
|
||||||
) -> None:
|
|
||||||
"""Set up the Camera that works with local files."""
|
|
||||||
file_path: str = config[CONF_FILE_PATH]
|
|
||||||
file_path_slug = slugify(file_path)
|
|
||||||
|
|
||||||
if not await hass.async_add_executor_job(check_file_path_access, file_path):
|
|
||||||
ir.async_create_issue(
|
|
||||||
hass,
|
|
||||||
DOMAIN,
|
|
||||||
f"no_access_path_{file_path_slug}",
|
|
||||||
breaks_in_ha_version="2025.5.0",
|
|
||||||
is_fixable=False,
|
|
||||||
learn_more_url="https://www.home-assistant.io/integrations/local_file/",
|
|
||||||
severity=ir.IssueSeverity.WARNING,
|
|
||||||
translation_key="no_access_path",
|
|
||||||
translation_placeholders={
|
|
||||||
"file_path": file_path_slug,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
return
|
|
||||||
|
|
||||||
ir.async_create_issue(
|
|
||||||
hass,
|
|
||||||
HOMEASSISTANT_DOMAIN,
|
|
||||||
f"deprecated_yaml_{DOMAIN}",
|
|
||||||
breaks_in_ha_version="2025.5.0",
|
|
||||||
is_fixable=False,
|
|
||||||
issue_domain=DOMAIN,
|
|
||||||
learn_more_url="https://www.home-assistant.io/integrations/local_file/",
|
|
||||||
severity=ir.IssueSeverity.WARNING,
|
|
||||||
translation_key="deprecated_yaml",
|
|
||||||
translation_placeholders={
|
|
||||||
"domain": DOMAIN,
|
|
||||||
"integration_title": "Local file",
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
hass.async_create_task(
|
|
||||||
hass.config_entries.flow.async_init(
|
|
||||||
DOMAIN,
|
|
||||||
context={"source": SOURCE_IMPORT},
|
|
||||||
data=config,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class LocalFile(Camera):
|
class LocalFile(Camera):
|
||||||
"""Representation of a local file camera."""
|
"""Representation of a local file camera."""
|
||||||
|
|
||||||
|
@ -50,18 +50,12 @@ DATA_SCHEMA_SETUP = vol.Schema(
|
|||||||
|
|
||||||
CONFIG_FLOW = {
|
CONFIG_FLOW = {
|
||||||
"user": SchemaFlowFormStep(
|
"user": SchemaFlowFormStep(
|
||||||
schema=DATA_SCHEMA_SETUP,
|
schema=DATA_SCHEMA_SETUP, validate_user_input=validate_options
|
||||||
validate_user_input=validate_options,
|
)
|
||||||
),
|
|
||||||
"import": SchemaFlowFormStep(
|
|
||||||
schema=DATA_SCHEMA_SETUP,
|
|
||||||
validate_user_input=validate_options,
|
|
||||||
),
|
|
||||||
}
|
}
|
||||||
OPTIONS_FLOW = {
|
OPTIONS_FLOW = {
|
||||||
"init": SchemaFlowFormStep(
|
"init": SchemaFlowFormStep(
|
||||||
DATA_SCHEMA_OPTIONS,
|
DATA_SCHEMA_OPTIONS, validate_user_input=validate_options
|
||||||
validate_user_input=validate_options,
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,11 +53,5 @@
|
|||||||
"file_path_not_accessible": {
|
"file_path_not_accessible": {
|
||||||
"message": "Path {file_path} is not accessible"
|
"message": "Path {file_path} is not accessible"
|
||||||
}
|
}
|
||||||
},
|
|
||||||
"issues": {
|
|
||||||
"no_access_path": {
|
|
||||||
"title": "Incorrect file path",
|
|
||||||
"description": "While trying to import your configuration the provided file path {file_path} could not be read.\nPlease update your configuration to a correct file path and restart to fix this issue."
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,11 +13,8 @@ from homeassistant.components.local_file.const import (
|
|||||||
)
|
)
|
||||||
from homeassistant.config_entries import SOURCE_USER
|
from homeassistant.config_entries import SOURCE_USER
|
||||||
from homeassistant.const import ATTR_ENTITY_ID, CONF_FILE_PATH
|
from homeassistant.const import ATTR_ENTITY_ID, CONF_FILE_PATH
|
||||||
from homeassistant.core import DOMAIN as HOMEASSISTANT_DOMAIN, HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.exceptions import ServiceValidationError
|
from homeassistant.exceptions import ServiceValidationError
|
||||||
from homeassistant.helpers import issue_registry as ir
|
|
||||||
from homeassistant.setup import async_setup_component
|
|
||||||
from homeassistant.util import slugify
|
|
||||||
|
|
||||||
from tests.common import MockConfigEntry
|
from tests.common import MockConfigEntry
|
||||||
from tests.typing import ClientSessionGenerator
|
from tests.typing import ClientSessionGenerator
|
||||||
@ -212,76 +209,3 @@ async def test_update_file_path(
|
|||||||
service_data,
|
service_data,
|
||||||
blocking=True,
|
blocking=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
async def test_import_from_yaml_success(
|
|
||||||
hass: HomeAssistant, issue_registry: ir.IssueRegistry
|
|
||||||
) -> None:
|
|
||||||
"""Test import."""
|
|
||||||
|
|
||||||
with (
|
|
||||||
patch("os.path.isfile", Mock(return_value=True)),
|
|
||||||
patch("os.access", Mock(return_value=True)),
|
|
||||||
patch(
|
|
||||||
"homeassistant.components.local_file.camera.mimetypes.guess_type",
|
|
||||||
Mock(return_value=(None, None)),
|
|
||||||
),
|
|
||||||
):
|
|
||||||
await async_setup_component(
|
|
||||||
hass,
|
|
||||||
"camera",
|
|
||||||
{
|
|
||||||
"camera": {
|
|
||||||
"name": "config_test",
|
|
||||||
"platform": "local_file",
|
|
||||||
"file_path": "mock.file",
|
|
||||||
}
|
|
||||||
},
|
|
||||||
)
|
|
||||||
await hass.async_block_till_done()
|
|
||||||
|
|
||||||
assert hass.config_entries.async_has_entries(DOMAIN)
|
|
||||||
state = hass.states.get("camera.config_test")
|
|
||||||
assert state.attributes.get("file_path") == "mock.file"
|
|
||||||
|
|
||||||
issue = issue_registry.async_get_issue(
|
|
||||||
HOMEASSISTANT_DOMAIN, f"deprecated_yaml_{DOMAIN}"
|
|
||||||
)
|
|
||||||
assert issue
|
|
||||||
assert issue.translation_key == "deprecated_yaml"
|
|
||||||
|
|
||||||
|
|
||||||
async def test_import_from_yaml_fails(
|
|
||||||
hass: HomeAssistant, issue_registry: ir.IssueRegistry
|
|
||||||
) -> None:
|
|
||||||
"""Test import fails due to not accessible file."""
|
|
||||||
|
|
||||||
with (
|
|
||||||
patch("os.path.isfile", Mock(return_value=True)),
|
|
||||||
patch("os.access", Mock(return_value=False)),
|
|
||||||
patch(
|
|
||||||
"homeassistant.components.local_file.camera.mimetypes.guess_type",
|
|
||||||
Mock(return_value=(None, None)),
|
|
||||||
),
|
|
||||||
):
|
|
||||||
await async_setup_component(
|
|
||||||
hass,
|
|
||||||
"camera",
|
|
||||||
{
|
|
||||||
"camera": {
|
|
||||||
"name": "config_test",
|
|
||||||
"platform": "local_file",
|
|
||||||
"file_path": "mock.file",
|
|
||||||
}
|
|
||||||
},
|
|
||||||
)
|
|
||||||
await hass.async_block_till_done()
|
|
||||||
|
|
||||||
assert not hass.config_entries.async_has_entries(DOMAIN)
|
|
||||||
assert not hass.states.get("camera.config_test")
|
|
||||||
|
|
||||||
issue = issue_registry.async_get_issue(
|
|
||||||
DOMAIN, f"no_access_path_{slugify('mock.file')}"
|
|
||||||
)
|
|
||||||
assert issue
|
|
||||||
assert issue.translation_key == "no_access_path"
|
|
||||||
|
@ -175,61 +175,3 @@ async def test_entry_already_exist(
|
|||||||
|
|
||||||
assert result["type"] is FlowResultType.ABORT
|
assert result["type"] is FlowResultType.ABORT
|
||||||
assert result["reason"] == "already_configured"
|
assert result["reason"] == "already_configured"
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.usefixtures("mock_setup_entry")
|
|
||||||
async def test_import(hass: HomeAssistant) -> None:
|
|
||||||
"""Test import."""
|
|
||||||
|
|
||||||
with (
|
|
||||||
patch("os.path.isfile", Mock(return_value=True)),
|
|
||||||
patch("os.access", Mock(return_value=True)),
|
|
||||||
patch(
|
|
||||||
"homeassistant.components.local_file.camera.mimetypes.guess_type",
|
|
||||||
Mock(return_value=(None, None)),
|
|
||||||
),
|
|
||||||
):
|
|
||||||
result = await hass.config_entries.flow.async_init(
|
|
||||||
DOMAIN,
|
|
||||||
context={"source": config_entries.SOURCE_IMPORT},
|
|
||||||
data={
|
|
||||||
"name": DEFAULT_NAME,
|
|
||||||
"file_path": "mock/path.jpg",
|
|
||||||
},
|
|
||||||
)
|
|
||||||
await hass.async_block_till_done()
|
|
||||||
|
|
||||||
assert result["type"] is FlowResultType.CREATE_ENTRY
|
|
||||||
assert result["version"] == 1
|
|
||||||
assert result["options"] == {
|
|
||||||
CONF_NAME: DEFAULT_NAME,
|
|
||||||
CONF_FILE_PATH: "mock/path.jpg",
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.usefixtures("mock_setup_entry")
|
|
||||||
async def test_import_already_exist(
|
|
||||||
hass: HomeAssistant, loaded_entry: MockConfigEntry
|
|
||||||
) -> None:
|
|
||||||
"""Test import abort existing entry."""
|
|
||||||
|
|
||||||
with (
|
|
||||||
patch("os.path.isfile", Mock(return_value=True)),
|
|
||||||
patch("os.access", Mock(return_value=True)),
|
|
||||||
patch(
|
|
||||||
"homeassistant.components.local_file.camera.mimetypes.guess_type",
|
|
||||||
Mock(return_value=(None, None)),
|
|
||||||
),
|
|
||||||
):
|
|
||||||
result = await hass.config_entries.flow.async_init(
|
|
||||||
DOMAIN,
|
|
||||||
context={"source": config_entries.SOURCE_IMPORT},
|
|
||||||
data={
|
|
||||||
CONF_NAME: DEFAULT_NAME,
|
|
||||||
CONF_FILE_PATH: "mock.file",
|
|
||||||
},
|
|
||||||
)
|
|
||||||
await hass.async_block_till_done()
|
|
||||||
|
|
||||||
assert result["type"] is FlowResultType.ABORT
|
|
||||||
assert result["reason"] == "already_configured"
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user