diff --git a/homeassistant/components/dlna_dmr/config_flow.py b/homeassistant/components/dlna_dmr/config_flow.py index 69437d99e3d..d3c1b6ca845 100644 --- a/homeassistant/components/dlna_dmr/config_flow.py +++ b/homeassistant/components/dlna_dmr/config_flow.py @@ -14,13 +14,7 @@ import voluptuous as vol from homeassistant import config_entries from homeassistant.components import ssdp -from homeassistant.const import ( - CONF_DEVICE_ID, - CONF_HOST, - CONF_NAME, - CONF_TYPE, - CONF_URL, -) +from homeassistant.const import CONF_DEVICE_ID, CONF_HOST, CONF_TYPE, CONF_URL from homeassistant.core import callback from homeassistant.data_entry_flow import FlowResult from homeassistant.exceptions import IntegrationError @@ -125,85 +119,6 @@ class DlnaDmrFlowHandler(config_entries.ConfigFlow, domain=DOMAIN): step_id="manual", data_schema=data_schema, errors=errors ) - async def async_step_import(self, import_data: FlowInput = None) -> FlowResult: - """Import a new DLNA DMR device from a config entry. - - This flow is triggered by `async_setup_platform`. If the device has not - been migrated, and can be connected to, automatically import it. If it - cannot be connected to, prompt the user to turn it on. If it has already - been migrated, do nothing. - """ - LOGGER.debug("async_step_import: import_data: %s", import_data) - - if not import_data or CONF_URL not in import_data: - LOGGER.debug("Entry not imported: incomplete_config") - return self.async_abort(reason="incomplete_config") - - self._location = import_data[CONF_URL] - self._async_abort_entries_match({CONF_URL: self._location}) - - # Use the location as this config flow's unique ID until UDN is known - await self.async_set_unique_id(self._location) - - # Set options from the import_data, except listen_ip which is no longer used - self._options[CONF_LISTEN_PORT] = import_data.get(CONF_LISTEN_PORT) - self._options[CONF_CALLBACK_URL_OVERRIDE] = import_data.get( - CONF_CALLBACK_URL_OVERRIDE - ) - - # Override device name if it's set in the YAML - self._name = import_data.get(CONF_NAME) - - discoveries = await self._async_get_discoveries() - - # Find the device in the list of unconfigured devices - for discovery in discoveries: - if discovery.ssdp_location == self._location: - # Device found via SSDP, it shouldn't need polling - self._options[CONF_POLL_AVAILABILITY] = False - # Discovery info has everything required to create config entry - await self._async_set_info_from_discovery(discovery) - LOGGER.debug( - "Entry %s found via SSDP, with UDN %s", - self._location, - self._udn, - ) - return self._create_entry() - - # This device will need to be polled - self._options[CONF_POLL_AVAILABILITY] = True - - # Device was not found via SSDP, connect directly for configuration - try: - await self._async_connect() - except ConnectError as err: - # This will require user action - LOGGER.debug("Entry %s not imported yet: %s", self._location, err.args[0]) - return await self.async_step_import_turn_on() - - LOGGER.debug("Entry %s ready for import", self._location) - return self._create_entry() - - async def async_step_import_turn_on( - self, user_input: FlowInput = None - ) -> FlowResult: - """Request the user to turn on the device so that import can finish.""" - LOGGER.debug("async_step_import_turn_on: %s", user_input) - - self.context["title_placeholders"] = {"name": self._name or self._location} - - errors = {} - if user_input is not None: - try: - await self._async_connect() - except ConnectError as err: - errors["base"] = err.args[0] - else: - return self._create_entry() - - self._set_confirm_only() - return self.async_show_form(step_id="import_turn_on", errors=errors) - async def async_step_ssdp(self, discovery_info: ssdp.SsdpServiceInfo) -> FlowResult: """Handle a flow initialized by SSDP discovery.""" LOGGER.debug("async_step_ssdp: discovery_info %s", pformat(discovery_info)) diff --git a/homeassistant/components/dlna_dmr/media_player.py b/homeassistant/components/dlna_dmr/media_player.py index 2b529609d9e..1b64f592460 100644 --- a/homeassistant/components/dlna_dmr/media_player.py +++ b/homeassistant/components/dlna_dmr/media_player.py @@ -13,11 +13,10 @@ from async_upnp_client.const import NotificationSubType from async_upnp_client.exceptions import UpnpError, UpnpResponseError from async_upnp_client.profiles.dlna import DmrDevice, PlayMode, TransportState from async_upnp_client.utils import async_get_local_ip -import voluptuous as vol from homeassistant import config_entries from homeassistant.components import ssdp -from homeassistant.components.media_player import PLATFORM_SCHEMA, MediaPlayerEntity +from homeassistant.components.media_player import MediaPlayerEntity from homeassistant.components.media_player.const import ( ATTR_MEDIA_EXTRA, REPEAT_MODE_ALL, @@ -38,7 +37,6 @@ from homeassistant.components.media_player.const import ( ) from homeassistant.const import ( CONF_DEVICE_ID, - CONF_NAME, CONF_TYPE, CONF_URL, STATE_IDLE, @@ -49,9 +47,7 @@ from homeassistant.const import ( ) from homeassistant.core import HomeAssistant from homeassistant.helpers import device_registry, entity_registry -import homeassistant.helpers.config_validation as cv from homeassistant.helpers.entity_platform import AddEntitiesCallback -from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType from .const import ( CONF_CALLBACK_URL_OVERRIDE, @@ -69,25 +65,6 @@ from .data import EventListenAddr, get_domain_data PARALLEL_UPDATES = 0 -# Configuration via YAML is deprecated in favour of config flow -CONF_LISTEN_IP = "listen_ip" -PLATFORM_SCHEMA = vol.All( - cv.deprecated(CONF_URL), - cv.deprecated(CONF_LISTEN_IP), - cv.deprecated(CONF_LISTEN_PORT), - cv.deprecated(CONF_NAME), - cv.deprecated(CONF_CALLBACK_URL_OVERRIDE), - PLATFORM_SCHEMA.extend( - { - vol.Required(CONF_URL): cv.string, - vol.Optional(CONF_LISTEN_IP): cv.string, - vol.Optional(CONF_LISTEN_PORT): cv.port, - vol.Optional(CONF_NAME): cv.string, - vol.Optional(CONF_CALLBACK_URL_OVERRIDE): cv.url, - } - ), -) - Func = TypeVar("Func", bound=Callable[..., Any]) @@ -111,29 +88,6 @@ def catch_request_errors(func: Func) -> Func: return cast(Func, wrapper) -async def async_setup_platform( - hass: HomeAssistant, - config: ConfigType, - async_add_entities: AddEntitiesCallback, - discovery_info: DiscoveryInfoType | None = None, -) -> None: - """Set up DLNA media_player platform.""" - hass.async_create_task( - hass.config_entries.flow.async_init( - DOMAIN, - context={"source": config_entries.SOURCE_IMPORT}, - data=config, - ) - ) - - _LOGGER.warning( - "Configuring dlna_dmr via yaml is deprecated; the configuration for" - " %s will be migrated to a config entry and can be safely removed when" - "migration is complete", - config.get(CONF_URL), - ) - - async def async_setup_entry( hass: HomeAssistant, entry: config_entries.ConfigEntry, diff --git a/tests/components/dlna_dmr/test_config_flow.py b/tests/components/dlna_dmr/test_config_flow.py index c497d45a4f2..fb0c416c086 100644 --- a/tests/components/dlna_dmr/test_config_flow.py +++ b/tests/components/dlna_dmr/test_config_flow.py @@ -15,14 +15,7 @@ from homeassistant.components.dlna_dmr.const import ( CONF_POLL_AVAILABILITY, DOMAIN as DLNA_DOMAIN, ) -from homeassistant.const import ( - CONF_DEVICE_ID, - CONF_HOST, - CONF_NAME, - CONF_PLATFORM, - CONF_TYPE, - CONF_URL, -) +from homeassistant.const import CONF_DEVICE_ID, CONF_HOST, CONF_TYPE, CONF_URL from homeassistant.core import HomeAssistant from .conftest import ( @@ -43,13 +36,6 @@ pytestmark = [ WRONG_DEVICE_TYPE = "urn:schemas-upnp-org:device:InternetGatewayDevice:1" -IMPORTED_DEVICE_NAME = "Imported DMR device" - -MOCK_CONFIG_IMPORT_DATA = { - CONF_PLATFORM: DLNA_DOMAIN, - CONF_URL: MOCK_DEVICE_LOCATION, -} - MOCK_ROOT_DEVICE_UDN = "ROOT_DEVICE" MOCK_DISCOVERY = ssdp.SsdpServiceInfo( @@ -276,212 +262,6 @@ async def test_user_flow_wrong_st(hass: HomeAssistant, domain_data_mock: Mock) - assert result["step_id"] == "manual" -async def test_import_flow_invalid(hass: HomeAssistant, domain_data_mock: Mock) -> None: - """Test import flow of invalid YAML config.""" - # Missing CONF_URL - result = await hass.config_entries.flow.async_init( - DLNA_DOMAIN, - context={"source": config_entries.SOURCE_IMPORT}, - data={CONF_PLATFORM: DLNA_DOMAIN}, - ) - assert result["type"] == data_entry_flow.RESULT_TYPE_ABORT - assert result["reason"] == "incomplete_config" - - -async def test_import_flow_ssdp_discovered( - hass: HomeAssistant, ssdp_scanner_mock: Mock -) -> None: - """Test import of YAML config with a device also found via SSDP.""" - ssdp_scanner_mock.async_get_discovery_info_by_st.side_effect = [ - [MOCK_DISCOVERY], - [], - [], - ] - result = await hass.config_entries.flow.async_init( - DLNA_DOMAIN, - context={"source": config_entries.SOURCE_IMPORT}, - data=MOCK_CONFIG_IMPORT_DATA, - ) - await hass.async_block_till_done() - - assert ssdp_scanner_mock.async_get_discovery_info_by_st.call_count >= 1 - assert result["type"] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY - assert result["title"] == MOCK_DEVICE_NAME - assert result["data"] == { - CONF_URL: MOCK_DEVICE_LOCATION, - CONF_DEVICE_ID: MOCK_DEVICE_UDN, - CONF_TYPE: MOCK_DEVICE_TYPE, - } - assert result["options"] == { - CONF_LISTEN_PORT: None, - CONF_CALLBACK_URL_OVERRIDE: None, - CONF_POLL_AVAILABILITY: False, - } - - # The config entry should not be duplicated when dlna_dmr is restarted - ssdp_scanner_mock.async_get_discovery_info_by_st.side_effect = [ - [MOCK_DISCOVERY], - [], - [], - ] - result = await hass.config_entries.flow.async_init( - DLNA_DOMAIN, - context={"source": config_entries.SOURCE_IMPORT}, - data=MOCK_CONFIG_IMPORT_DATA, - ) - assert result["type"] == data_entry_flow.RESULT_TYPE_ABORT - assert result["reason"] == "already_configured" - - # Wait for platform to be fully setup - await hass.async_block_till_done() - - -async def test_import_flow_direct_connect( - hass: HomeAssistant, ssdp_scanner_mock: Mock -) -> None: - """Test import of YAML config with a device *not found* via SSDP.""" - ssdp_scanner_mock.async_get_discovery_info_by_st.return_value = [] - - result = await hass.config_entries.flow.async_init( - DLNA_DOMAIN, - context={"source": config_entries.SOURCE_IMPORT}, - data=MOCK_CONFIG_IMPORT_DATA, - ) - await hass.async_block_till_done() - - assert ssdp_scanner_mock.async_get_discovery_info_by_st.call_count >= 1 - assert result["type"] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY - assert result["title"] == MOCK_DEVICE_NAME - assert result["data"] == { - CONF_URL: MOCK_DEVICE_LOCATION, - CONF_DEVICE_ID: MOCK_DEVICE_UDN, - CONF_TYPE: MOCK_DEVICE_TYPE, - } - assert result["options"] == { - CONF_LISTEN_PORT: None, - CONF_CALLBACK_URL_OVERRIDE: None, - CONF_POLL_AVAILABILITY: True, - } - - # The config entry should not be duplicated when dlna_dmr is restarted - result = await hass.config_entries.flow.async_init( - DLNA_DOMAIN, - context={"source": config_entries.SOURCE_IMPORT}, - data=MOCK_CONFIG_IMPORT_DATA, - ) - assert result["type"] == data_entry_flow.RESULT_TYPE_ABORT - assert result["reason"] == "already_configured" - - -async def test_import_flow_offline( - hass: HomeAssistant, domain_data_mock: Mock, ssdp_scanner_mock: Mock -) -> None: - """Test import flow of offline device.""" - # Device is not yet contactable - domain_data_mock.upnp_factory.async_create_device.side_effect = UpnpError - - result = await hass.config_entries.flow.async_init( - DLNA_DOMAIN, - context={"source": config_entries.SOURCE_IMPORT}, - data={ - CONF_PLATFORM: DLNA_DOMAIN, - CONF_URL: MOCK_DEVICE_LOCATION, - CONF_NAME: IMPORTED_DEVICE_NAME, - CONF_CALLBACK_URL_OVERRIDE: "http://override/callback", - CONF_LISTEN_PORT: 2222, - }, - ) - assert result["type"] == data_entry_flow.RESULT_TYPE_FORM - assert result["errors"] == {} - assert result["step_id"] == "import_turn_on" - - import_flow_id = result["flow_id"] - - # User clicks submit, same form is displayed with an error - result = await hass.config_entries.flow.async_configure( - import_flow_id, user_input={} - ) - - assert result["type"] == data_entry_flow.RESULT_TYPE_FORM - assert result["errors"] == {"base": "cannot_connect"} - assert result["step_id"] == "import_turn_on" - - # Device is discovered via SSDP, new flow should not be initialized - ssdp_scanner_mock.async_get_discovery_info_by_st.side_effect = [ - [MOCK_DISCOVERY], - [], - [], - ] - domain_data_mock.upnp_factory.async_create_device.side_effect = None - - result = await hass.config_entries.flow.async_init( - DLNA_DOMAIN, - context={"source": config_entries.SOURCE_SSDP}, - data=MOCK_DISCOVERY, - ) - - assert result["type"] == data_entry_flow.RESULT_TYPE_ABORT - assert result["reason"] == "already_in_progress" - - # User clicks submit, config entry should be created - result = await hass.config_entries.flow.async_configure( - import_flow_id, user_input={} - ) - - assert result["type"] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY - assert result["title"] == IMPORTED_DEVICE_NAME - assert result["data"] == { - CONF_URL: MOCK_DEVICE_LOCATION, - CONF_DEVICE_ID: MOCK_DEVICE_UDN, - CONF_TYPE: MOCK_DEVICE_TYPE, - } - # Options should be retained - assert result["options"] == { - CONF_LISTEN_PORT: 2222, - CONF_CALLBACK_URL_OVERRIDE: "http://override/callback", - CONF_POLL_AVAILABILITY: True, - } - - # Wait for platform to be fully setup - await hass.async_block_till_done() - - -async def test_import_flow_options( - hass: HomeAssistant, ssdp_scanner_mock: Mock -) -> None: - """Test import of YAML config with options set.""" - ssdp_scanner_mock.async_get_discovery_info_by_st.return_value = [] - - result = await hass.config_entries.flow.async_init( - DLNA_DOMAIN, - context={"source": config_entries.SOURCE_IMPORT}, - data={ - CONF_PLATFORM: DLNA_DOMAIN, - CONF_URL: MOCK_DEVICE_LOCATION, - CONF_NAME: IMPORTED_DEVICE_NAME, - CONF_LISTEN_PORT: 2222, - CONF_CALLBACK_URL_OVERRIDE: "http://override/callback", - }, - ) - await hass.async_block_till_done() - - assert result["type"] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY - assert result["title"] == IMPORTED_DEVICE_NAME - assert result["data"] == { - CONF_URL: MOCK_DEVICE_LOCATION, - CONF_DEVICE_ID: MOCK_DEVICE_UDN, - CONF_TYPE: MOCK_DEVICE_TYPE, - } - assert result["options"] == { - CONF_LISTEN_PORT: 2222, - CONF_CALLBACK_URL_OVERRIDE: "http://override/callback", - CONF_POLL_AVAILABILITY: True, - } - - # Wait for platform to be fully setup - await hass.async_block_till_done() - - async def test_ssdp_flow_success(hass: HomeAssistant) -> None: """Test that SSDP discovery with an available device works.""" result = await hass.config_entries.flow.async_init( diff --git a/tests/components/dlna_dmr/test_media_player.py b/tests/components/dlna_dmr/test_media_player.py index b8c10b47b60..2d59c31c666 100644 --- a/tests/components/dlna_dmr/test_media_player.py +++ b/tests/components/dlna_dmr/test_media_player.py @@ -29,7 +29,7 @@ from homeassistant.components.dlna_dmr.const import ( from homeassistant.components.dlna_dmr.data import EventListenAddr from homeassistant.components.media_player import ATTR_TO_PROPERTY, const as mp_const from homeassistant.components.media_player.const import DOMAIN as MP_DOMAIN -from homeassistant.const import ATTR_ENTITY_ID, CONF_PLATFORM, CONF_URL +from homeassistant.const import ATTR_ENTITY_ID from homeassistant.core import HomeAssistant from homeassistant.helpers.device_registry import async_get as async_get_dr from homeassistant.helpers.entity_component import async_update_entity @@ -37,7 +37,6 @@ from homeassistant.helpers.entity_registry import ( async_entries_for_config_entry, async_get as async_get_er, ) -from homeassistant.helpers.typing import ConfigType from homeassistant.setup import async_setup_component from .conftest import ( @@ -183,38 +182,6 @@ async def mock_disconnected_entity_id( assert dmr_device_mock.on_event is None -async def test_setup_platform_import_flow_started( - hass: HomeAssistant, domain_data_mock: Mock -) -> None: - """Test import flow of YAML config is started if there's config data.""" - # Cause connection attempts to fail - domain_data_mock.upnp_factory.async_create_device.side_effect = UpnpConnectionError - - # Run the setup - mock_config: ConfigType = { - MP_DOMAIN: [ - { - CONF_PLATFORM: DLNA_DOMAIN, - CONF_URL: MOCK_DEVICE_LOCATION, - CONF_LISTEN_PORT: 1234, - } - ] - } - - await async_setup_component(hass, MP_DOMAIN, mock_config) - await hass.async_block_till_done() - - # Check config_flow has started - flows = hass.config_entries.flow.async_progress(include_uninitialized=True) - assert len(flows) == 1 - - # It should be paused, waiting for the user to turn on the device - flow = flows[0] - assert flow["handler"] == "dlna_dmr" - assert flow["step_id"] == "import_turn_on" - assert flow["context"].get("unique_id") == MOCK_DEVICE_LOCATION - - async def test_setup_entry_no_options( hass: HomeAssistant, domain_data_mock: Mock,