diff --git a/homeassistant/components/onvif/config_flow.py b/homeassistant/components/onvif/config_flow.py index 0d0ddc180df..c1df94f5f83 100644 --- a/homeassistant/components/onvif/config_flow.py +++ b/homeassistant/components/onvif/config_flow.py @@ -51,12 +51,15 @@ CONF_MANUAL_INPUT = "Manually configure ONVIF device" def wsdiscovery() -> list[Service]: """Get ONVIF Profile S devices from network.""" discovery = WSDiscovery(ttl=4) - discovery.start() - services = discovery.searchServices( - scopes=[Scope("onvif://www.onvif.org/Profile/Streaming")] - ) - discovery.stop() - return services + try: + discovery.start() + return discovery.searchServices( + scopes=[Scope("onvif://www.onvif.org/Profile/Streaming")] + ) + finally: + discovery.stop() + # Stop the threads started by WSDiscovery since otherwise there is a leak. + discovery._stopThreads() # pylint: disable=protected-access async def async_discovery(hass: HomeAssistant) -> list[dict[str, Any]]: diff --git a/tests/components/onvif/test_config_flow.py b/tests/components/onvif/test_config_flow.py index adb8a33251c..00fc77076e8 100644 --- a/tests/components/onvif/test_config_flow.py +++ b/tests/components/onvif/test_config_flow.py @@ -60,10 +60,13 @@ def setup_mock_discovery( with_mac=False, two_devices=False, with_hardware=True, + no_devices=False, ): """Prepare mock discovery result.""" services = [] for item in DISCOVERY: + if no_devices: + continue service = MagicMock() service.getXAddrs = MagicMock( return_value=[ @@ -92,7 +95,10 @@ def setup_mock_discovery( scopes.append(scope) service.getScopes = MagicMock(return_value=scopes) services.append(service) - mock_discovery.return_value = services + + mock_ws_discovery = MagicMock() + mock_ws_discovery.searchServices = MagicMock(return_value=services) + mock_discovery.return_value = mock_ws_discovery async def test_flow_discovered_devices(hass: HomeAssistant) -> None: @@ -108,7 +114,7 @@ async def test_flow_discovered_devices(hass: HomeAssistant) -> None: with patch( "homeassistant.components.onvif.config_flow.get_device" ) as mock_onvif_camera, patch( - "homeassistant.components.onvif.config_flow.wsdiscovery" + "homeassistant.components.onvif.config_flow.WSDiscovery" ) as mock_discovery, patch( "homeassistant.components.onvif.ONVIFDevice" ) as mock_device: @@ -178,7 +184,7 @@ async def test_flow_discovered_devices_ignore_configured_manual_input( with patch( "homeassistant.components.onvif.config_flow.get_device" ) as mock_onvif_camera, patch( - "homeassistant.components.onvif.config_flow.wsdiscovery" + "homeassistant.components.onvif.config_flow.WSDiscovery" ) as mock_discovery, patch( "homeassistant.components.onvif.ONVIFDevice" ) as mock_device: @@ -217,12 +223,12 @@ async def test_flow_discovered_no_device(hass: HomeAssistant) -> None: with patch( "homeassistant.components.onvif.config_flow.get_device" ) as mock_onvif_camera, patch( - "homeassistant.components.onvif.config_flow.wsdiscovery" + "homeassistant.components.onvif.config_flow.WSDiscovery" ) as mock_discovery, patch( "homeassistant.components.onvif.ONVIFDevice" ) as mock_device: setup_mock_onvif_camera(mock_onvif_camera) - mock_discovery.return_value = [] + setup_mock_discovery(mock_discovery, no_devices=True) setup_mock_device(mock_device) result = await hass.config_entries.flow.async_configure( @@ -259,7 +265,7 @@ async def test_flow_discovery_ignore_existing_and_abort(hass: HomeAssistant) -> with patch( "homeassistant.components.onvif.config_flow.get_device" ) as mock_onvif_camera, patch( - "homeassistant.components.onvif.config_flow.wsdiscovery" + "homeassistant.components.onvif.config_flow.WSDiscovery" ) as mock_discovery, patch( "homeassistant.components.onvif.ONVIFDevice" ) as mock_device: @@ -302,7 +308,7 @@ async def test_flow_manual_entry(hass: HomeAssistant) -> None: with patch( "homeassistant.components.onvif.config_flow.get_device" ) as mock_onvif_camera, patch( - "homeassistant.components.onvif.config_flow.wsdiscovery" + "homeassistant.components.onvif.config_flow.WSDiscovery" ) as mock_discovery, patch( "homeassistant.components.onvif.ONVIFDevice" ) as mock_device: @@ -359,7 +365,7 @@ async def test_flow_manual_entry_no_profiles(hass: HomeAssistant) -> None: with patch( "homeassistant.components.onvif.config_flow.get_device" ) as mock_onvif_camera, patch( - "homeassistant.components.onvif.config_flow.wsdiscovery" + "homeassistant.components.onvif.config_flow.WSDiscovery" ) as mock_discovery, patch( "homeassistant.components.onvif.ONVIFDevice" ) as mock_device: @@ -399,7 +405,7 @@ async def test_flow_manual_entry_no_mac(hass: HomeAssistant) -> None: with patch( "homeassistant.components.onvif.config_flow.get_device" ) as mock_onvif_camera, patch( - "homeassistant.components.onvif.config_flow.wsdiscovery" + "homeassistant.components.onvif.config_flow.WSDiscovery" ) as mock_discovery, patch( "homeassistant.components.onvif.ONVIFDevice" ) as mock_device: @@ -441,7 +447,7 @@ async def test_flow_manual_entry_fails(hass: HomeAssistant) -> None: with patch( "homeassistant.components.onvif.config_flow.get_device" ) as mock_onvif_camera, patch( - "homeassistant.components.onvif.config_flow.wsdiscovery" + "homeassistant.components.onvif.config_flow.WSDiscovery" ) as mock_discovery, patch( "homeassistant.components.onvif.ONVIFDevice" ) as mock_device: @@ -549,7 +555,7 @@ async def test_flow_manual_entry_wrong_password(hass: HomeAssistant) -> None: with patch( "homeassistant.components.onvif.config_flow.get_device" ) as mock_onvif_camera, patch( - "homeassistant.components.onvif.config_flow.wsdiscovery" + "homeassistant.components.onvif.config_flow.WSDiscovery" ) as mock_discovery, patch( "homeassistant.components.onvif.ONVIFDevice" ) as mock_device: @@ -826,7 +832,7 @@ async def test_flow_manual_entry_updates_existing_user_password( with patch( "homeassistant.components.onvif.config_flow.get_device" ) as mock_onvif_camera, patch( - "homeassistant.components.onvif.config_flow.wsdiscovery" + "homeassistant.components.onvif.config_flow.WSDiscovery" ) as mock_discovery, patch( "homeassistant.components.onvif.ONVIFDevice" ) as mock_device: @@ -877,7 +883,7 @@ async def test_flow_manual_entry_wrong_port(hass: HomeAssistant) -> None: with patch( "homeassistant.components.onvif.config_flow.get_device" ) as mock_onvif_camera, patch( - "homeassistant.components.onvif.config_flow.wsdiscovery" + "homeassistant.components.onvif.config_flow.WSDiscovery" ) as mock_discovery, patch( "homeassistant.components.onvif.ONVIFDevice" ) as mock_device: