mirror of
https://github.com/home-assistant/core.git
synced 2025-07-23 05:07:41 +00:00
Remove yaml import from feedreader integration (#132278)
* Remove yaml import from feedreader integration * Update homeassistant/components/feedreader/config_flow.py Co-authored-by: epenet <6771947+epenet@users.noreply.github.com> * Drop _max_entries class attribute --------- Co-authored-by: epenet <6771947+epenet@users.noreply.github.com>
This commit is contained in:
parent
e5851c20e9
commit
3a2460f9f9
@ -2,17 +2,12 @@
|
|||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import voluptuous as vol
|
from homeassistant.config_entries import ConfigEntry
|
||||||
|
from homeassistant.const import CONF_URL, Platform
|
||||||
from homeassistant.config_entries import SOURCE_IMPORT, ConfigEntry
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.const import CONF_SCAN_INTERVAL, CONF_URL, Platform
|
|
||||||
from homeassistant.core import DOMAIN as HOMEASSISTANT_DOMAIN, HomeAssistant
|
|
||||||
import homeassistant.helpers.config_validation as cv
|
|
||||||
from homeassistant.helpers.issue_registry import IssueSeverity, async_create_issue
|
|
||||||
from homeassistant.helpers.typing import ConfigType
|
|
||||||
from homeassistant.util.hass_dict import HassKey
|
from homeassistant.util.hass_dict import HassKey
|
||||||
|
|
||||||
from .const import CONF_MAX_ENTRIES, DEFAULT_MAX_ENTRIES, DEFAULT_SCAN_INTERVAL, DOMAIN
|
from .const import CONF_MAX_ENTRIES, DOMAIN
|
||||||
from .coordinator import FeedReaderCoordinator, StoredData
|
from .coordinator import FeedReaderCoordinator, StoredData
|
||||||
|
|
||||||
type FeedReaderConfigEntry = ConfigEntry[FeedReaderCoordinator]
|
type FeedReaderConfigEntry = ConfigEntry[FeedReaderCoordinator]
|
||||||
@ -21,60 +16,6 @@ CONF_URLS = "urls"
|
|||||||
|
|
||||||
MY_KEY: HassKey[StoredData] = HassKey(DOMAIN)
|
MY_KEY: HassKey[StoredData] = HassKey(DOMAIN)
|
||||||
|
|
||||||
CONFIG_SCHEMA = vol.Schema(
|
|
||||||
vol.All(
|
|
||||||
cv.deprecated(DOMAIN),
|
|
||||||
{
|
|
||||||
DOMAIN: vol.Schema(
|
|
||||||
{
|
|
||||||
vol.Required(CONF_URLS): vol.All(cv.ensure_list, [cv.url]),
|
|
||||||
vol.Optional(
|
|
||||||
CONF_SCAN_INTERVAL, default=DEFAULT_SCAN_INTERVAL
|
|
||||||
): cv.time_period,
|
|
||||||
vol.Optional(
|
|
||||||
CONF_MAX_ENTRIES, default=DEFAULT_MAX_ENTRIES
|
|
||||||
): cv.positive_int,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
},
|
|
||||||
),
|
|
||||||
extra=vol.ALLOW_EXTRA,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
|
||||||
"""Set up the Feedreader component."""
|
|
||||||
if DOMAIN in config:
|
|
||||||
for url in config[DOMAIN][CONF_URLS]:
|
|
||||||
hass.async_create_task(
|
|
||||||
hass.config_entries.flow.async_init(
|
|
||||||
DOMAIN,
|
|
||||||
context={"source": SOURCE_IMPORT},
|
|
||||||
data={
|
|
||||||
CONF_URL: url,
|
|
||||||
CONF_MAX_ENTRIES: config[DOMAIN][CONF_MAX_ENTRIES],
|
|
||||||
},
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
async_create_issue(
|
|
||||||
hass,
|
|
||||||
HOMEASSISTANT_DOMAIN,
|
|
||||||
f"deprecated_yaml_{DOMAIN}",
|
|
||||||
breaks_in_ha_version="2025.1.0",
|
|
||||||
is_fixable=False,
|
|
||||||
is_persistent=False,
|
|
||||||
issue_domain=DOMAIN,
|
|
||||||
severity=IssueSeverity.WARNING,
|
|
||||||
translation_key="deprecated_yaml",
|
|
||||||
translation_placeholders={
|
|
||||||
"domain": DOMAIN,
|
|
||||||
"integration_title": "Feedreader",
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
return True
|
|
||||||
|
|
||||||
|
|
||||||
async def async_setup_entry(hass: HomeAssistant, entry: FeedReaderConfigEntry) -> bool:
|
async def async_setup_entry(hass: HomeAssistant, entry: FeedReaderConfigEntry) -> bool:
|
||||||
"""Set up Feedreader from a config entry."""
|
"""Set up Feedreader from a config entry."""
|
||||||
|
@ -11,7 +11,6 @@ import feedparser
|
|||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
from homeassistant.config_entries import (
|
from homeassistant.config_entries import (
|
||||||
SOURCE_IMPORT,
|
|
||||||
ConfigEntry,
|
ConfigEntry,
|
||||||
ConfigFlow,
|
ConfigFlow,
|
||||||
ConfigFlowResult,
|
ConfigFlowResult,
|
||||||
@ -20,13 +19,11 @@ from homeassistant.config_entries import (
|
|||||||
from homeassistant.const import CONF_URL
|
from homeassistant.const import CONF_URL
|
||||||
from homeassistant.core import HomeAssistant, callback
|
from homeassistant.core import HomeAssistant, callback
|
||||||
import homeassistant.helpers.config_validation as cv
|
import homeassistant.helpers.config_validation as cv
|
||||||
from homeassistant.helpers.issue_registry import IssueSeverity, async_create_issue
|
|
||||||
from homeassistant.helpers.selector import (
|
from homeassistant.helpers.selector import (
|
||||||
TextSelector,
|
TextSelector,
|
||||||
TextSelectorConfig,
|
TextSelectorConfig,
|
||||||
TextSelectorType,
|
TextSelectorType,
|
||||||
)
|
)
|
||||||
from homeassistant.util import slugify
|
|
||||||
|
|
||||||
from .const import CONF_MAX_ENTRIES, DEFAULT_MAX_ENTRIES, DOMAIN
|
from .const import CONF_MAX_ENTRIES, DEFAULT_MAX_ENTRIES, DOMAIN
|
||||||
|
|
||||||
@ -42,7 +39,6 @@ class FeedReaderConfigFlow(ConfigFlow, domain=DOMAIN):
|
|||||||
"""Handle a config flow."""
|
"""Handle a config flow."""
|
||||||
|
|
||||||
VERSION = 1
|
VERSION = 1
|
||||||
_max_entries: int | None = None
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
@callback
|
@callback
|
||||||
@ -75,21 +71,6 @@ class FeedReaderConfigFlow(ConfigFlow, domain=DOMAIN):
|
|||||||
errors=errors,
|
errors=errors,
|
||||||
)
|
)
|
||||||
|
|
||||||
def abort_on_import_error(self, url: str, error: str) -> ConfigFlowResult:
|
|
||||||
"""Abort import flow on error."""
|
|
||||||
async_create_issue(
|
|
||||||
self.hass,
|
|
||||||
DOMAIN,
|
|
||||||
f"import_yaml_error_{DOMAIN}_{error}_{slugify(url)}",
|
|
||||||
breaks_in_ha_version="2025.1.0",
|
|
||||||
is_fixable=False,
|
|
||||||
issue_domain=DOMAIN,
|
|
||||||
severity=IssueSeverity.WARNING,
|
|
||||||
translation_key=f"import_yaml_error_{error}",
|
|
||||||
translation_placeholders={"url": url},
|
|
||||||
)
|
|
||||||
return self.async_abort(reason=error)
|
|
||||||
|
|
||||||
async def async_step_user(
|
async def async_step_user(
|
||||||
self, user_input: dict[str, Any] | None = None
|
self, user_input: dict[str, Any] | None = None
|
||||||
) -> ConfigFlowResult:
|
) -> ConfigFlowResult:
|
||||||
@ -104,8 +85,6 @@ class FeedReaderConfigFlow(ConfigFlow, domain=DOMAIN):
|
|||||||
if feed.bozo:
|
if feed.bozo:
|
||||||
LOGGER.debug("feed bozo_exception: %s", feed.bozo_exception)
|
LOGGER.debug("feed bozo_exception: %s", feed.bozo_exception)
|
||||||
if isinstance(feed.bozo_exception, urllib.error.URLError):
|
if isinstance(feed.bozo_exception, urllib.error.URLError):
|
||||||
if self.context["source"] == SOURCE_IMPORT:
|
|
||||||
return self.abort_on_import_error(user_input[CONF_URL], "url_error")
|
|
||||||
return self.show_user_form(user_input, {"base": "url_error"})
|
return self.show_user_form(user_input, {"base": "url_error"})
|
||||||
|
|
||||||
feed_title = html.unescape(feed["feed"]["title"])
|
feed_title = html.unescape(feed["feed"]["title"])
|
||||||
@ -113,14 +92,9 @@ class FeedReaderConfigFlow(ConfigFlow, domain=DOMAIN):
|
|||||||
return self.async_create_entry(
|
return self.async_create_entry(
|
||||||
title=feed_title,
|
title=feed_title,
|
||||||
data=user_input,
|
data=user_input,
|
||||||
options={CONF_MAX_ENTRIES: self._max_entries or DEFAULT_MAX_ENTRIES},
|
options={CONF_MAX_ENTRIES: DEFAULT_MAX_ENTRIES},
|
||||||
)
|
)
|
||||||
|
|
||||||
async def async_step_import(self, import_data: dict[str, Any]) -> ConfigFlowResult:
|
|
||||||
"""Handle an import flow."""
|
|
||||||
self._max_entries = import_data[CONF_MAX_ENTRIES]
|
|
||||||
return await self.async_step_user({CONF_URL: import_data[CONF_URL]})
|
|
||||||
|
|
||||||
async def async_step_reconfigure(
|
async def async_step_reconfigure(
|
||||||
self, user_input: dict[str, Any] | None = None
|
self, user_input: dict[str, Any] | None = None
|
||||||
) -> ConfigFlowResult:
|
) -> ConfigFlowResult:
|
||||||
|
@ -5,7 +5,6 @@ import urllib
|
|||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from homeassistant.components.feedreader import CONF_URLS
|
|
||||||
from homeassistant.components.feedreader.const import (
|
from homeassistant.components.feedreader.const import (
|
||||||
CONF_MAX_ENTRIES,
|
CONF_MAX_ENTRIES,
|
||||||
DEFAULT_MAX_ENTRIES,
|
DEFAULT_MAX_ENTRIES,
|
||||||
@ -13,10 +12,8 @@ from homeassistant.components.feedreader.const import (
|
|||||||
)
|
)
|
||||||
from homeassistant.config_entries import SOURCE_USER
|
from homeassistant.config_entries import SOURCE_USER
|
||||||
from homeassistant.const import CONF_URL
|
from homeassistant.const import CONF_URL
|
||||||
from homeassistant.core import DOMAIN as HOMEASSISTANT_DOMAIN, HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.data_entry_flow import FlowResultType
|
from homeassistant.data_entry_flow import FlowResultType
|
||||||
from homeassistant.helpers import issue_registry as ir
|
|
||||||
from homeassistant.setup import async_setup_component
|
|
||||||
|
|
||||||
from . import create_mock_entry
|
from . import create_mock_entry
|
||||||
from .const import FEED_TITLE, URL, VALID_CONFIG_DEFAULT
|
from .const import FEED_TITLE, URL, VALID_CONFIG_DEFAULT
|
||||||
@ -95,65 +92,6 @@ async def test_user_errors(
|
|||||||
assert result["options"][CONF_MAX_ENTRIES] == DEFAULT_MAX_ENTRIES
|
assert result["options"][CONF_MAX_ENTRIES] == DEFAULT_MAX_ENTRIES
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
|
||||||
("data", "expected_data", "expected_options"),
|
|
||||||
[
|
|
||||||
({CONF_URLS: [URL]}, {CONF_URL: URL}, {CONF_MAX_ENTRIES: DEFAULT_MAX_ENTRIES}),
|
|
||||||
(
|
|
||||||
{CONF_URLS: [URL], CONF_MAX_ENTRIES: 5},
|
|
||||||
{CONF_URL: URL},
|
|
||||||
{CONF_MAX_ENTRIES: 5},
|
|
||||||
),
|
|
||||||
],
|
|
||||||
)
|
|
||||||
async def test_import(
|
|
||||||
hass: HomeAssistant,
|
|
||||||
issue_registry: ir.IssueRegistry,
|
|
||||||
data,
|
|
||||||
expected_data,
|
|
||||||
expected_options,
|
|
||||||
feedparser,
|
|
||||||
setup_entry,
|
|
||||||
) -> None:
|
|
||||||
"""Test starting an import flow."""
|
|
||||||
config_entries = hass.config_entries.async_entries(DOMAIN)
|
|
||||||
assert not config_entries
|
|
||||||
|
|
||||||
assert await async_setup_component(hass, DOMAIN, {DOMAIN: data})
|
|
||||||
|
|
||||||
config_entries = hass.config_entries.async_entries(DOMAIN)
|
|
||||||
assert config_entries
|
|
||||||
assert len(config_entries) == 1
|
|
||||||
assert config_entries[0].title == FEED_TITLE
|
|
||||||
assert config_entries[0].data == expected_data
|
|
||||||
assert config_entries[0].options == expected_options
|
|
||||||
|
|
||||||
assert issue_registry.async_get_issue(
|
|
||||||
HOMEASSISTANT_DOMAIN, "deprecated_yaml_feedreader"
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
async def test_import_errors(
|
|
||||||
hass: HomeAssistant,
|
|
||||||
issue_registry: ir.IssueRegistry,
|
|
||||||
feedparser,
|
|
||||||
setup_entry,
|
|
||||||
feed_one_event,
|
|
||||||
) -> None:
|
|
||||||
"""Test starting an import flow which results in an URL error."""
|
|
||||||
config_entries = hass.config_entries.async_entries(DOMAIN)
|
|
||||||
assert not config_entries
|
|
||||||
|
|
||||||
# raise URLError
|
|
||||||
feedparser.side_effect = urllib.error.URLError("Test")
|
|
||||||
feedparser.return_value = None
|
|
||||||
assert await async_setup_component(hass, DOMAIN, {DOMAIN: {CONF_URLS: [URL]}})
|
|
||||||
assert issue_registry.async_get_issue(
|
|
||||||
DOMAIN,
|
|
||||||
"import_yaml_error_feedreader_url_error_http_some_rss_local_rss_feed_xml",
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
async def test_reconfigure(hass: HomeAssistant, feedparser) -> None:
|
async def test_reconfigure(hass: HomeAssistant, feedparser) -> None:
|
||||||
"""Test starting a reconfigure flow."""
|
"""Test starting a reconfigure flow."""
|
||||||
entry = create_mock_entry(VALID_CONFIG_DEFAULT)
|
entry = create_mock_entry(VALID_CONFIG_DEFAULT)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user