Import and create pyudev for usb in the executor (#113478)
parent
29f07260f9
commit
b7f7bed46c
|
@ -35,7 +35,7 @@ from .models import USBDevice
|
|||
from .utils import usb_device_from_port
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from pyudev import Device
|
||||
from pyudev import Device, MonitorObserver
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
@ -228,6 +228,25 @@ class USBDiscovery:
|
|||
if info.get("docker"):
|
||||
return
|
||||
|
||||
if not (
|
||||
observer := await self.hass.async_add_executor_job(
|
||||
self._get_monitor_observer
|
||||
)
|
||||
):
|
||||
return
|
||||
|
||||
def _stop_observer(event: Event) -> None:
|
||||
observer.stop()
|
||||
|
||||
self.hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, _stop_observer)
|
||||
self.observer_active = True
|
||||
|
||||
def _get_monitor_observer(self) -> MonitorObserver | None:
|
||||
"""Get the monitor observer.
|
||||
|
||||
This runs in the executor because the import
|
||||
does blocking I/O.
|
||||
"""
|
||||
from pyudev import ( # pylint: disable=import-outside-toplevel
|
||||
Context,
|
||||
Monitor,
|
||||
|
@ -237,7 +256,7 @@ class USBDiscovery:
|
|||
try:
|
||||
context = Context()
|
||||
except (ImportError, OSError):
|
||||
return
|
||||
return None
|
||||
|
||||
monitor = Monitor.from_netlink(context)
|
||||
try:
|
||||
|
@ -246,17 +265,14 @@ class USBDiscovery:
|
|||
_LOGGER.debug(
|
||||
"Unable to setup pyudev filtering; This is expected on WSL: %s", ex
|
||||
)
|
||||
return
|
||||
return None
|
||||
|
||||
observer = MonitorObserver(
|
||||
monitor, callback=self._device_discovered, name="usb-observer"
|
||||
)
|
||||
|
||||
observer.start()
|
||||
|
||||
def _stop_observer(event: Event) -> None:
|
||||
observer.stop()
|
||||
|
||||
self.hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, _stop_observer)
|
||||
self.observer_active = True
|
||||
return observer
|
||||
|
||||
def _device_discovered(self, device: Device) -> None:
|
||||
"""Call when the observer discovers a new usb tty device."""
|
||||
|
|
|
@ -590,6 +590,7 @@ async def test_supervisor_issues_initial_failure(
|
|||
|
||||
with patch("homeassistant.components.hassio.issues.REQUEST_REFRESH_DELAY", new=0.1):
|
||||
result = await async_setup_component(hass, "hassio", {})
|
||||
await hass.async_block_till_done()
|
||||
assert result
|
||||
|
||||
client = await hass_ws_client(hass)
|
||||
|
|
|
@ -85,7 +85,7 @@ async def test_observer_discovery(
|
|||
|
||||
def _create_mock_monitor_observer(monitor, callback, name):
|
||||
nonlocal mock_observer
|
||||
hass.async_create_task(_mock_monitor_observer_callback(callback))
|
||||
hass.create_task(_mock_monitor_observer_callback(callback))
|
||||
mock_observer = MagicMock()
|
||||
return mock_observer
|
||||
|
||||
|
@ -107,7 +107,7 @@ async def test_observer_discovery(
|
|||
hass.bus.async_fire(EVENT_HOMEASSISTANT_STOP)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert mock_observer.mock_calls == [call.start(), call.stop()]
|
||||
assert mock_observer.mock_calls == [call.start(), call.__bool__(), call.stop()]
|
||||
|
||||
|
||||
@pytest.mark.skipif(
|
||||
|
|
Loading…
Reference in New Issue