def mock_timeout(hass, monkeypatch):
    """Mock async_timeout.timeout."""

    class MockTimeout:
        def __init__(self, timeout):
            self._timeout = timeout
            self._loop = asyncio.get_event_loop()
            self._task = None
            self._cancelled = False
            self._unsub = None

        async def __aenter__(self):
            if self._timeout is None:
                return self
            self._task = asyncio.Task.current_task()
            if self._timeout <= 0:
                self._loop.call_soon(self._cancel_task)
                return self
            # Wait for a time_changed event instead of real time passing.
            self._unsub = async_call_later(hass, self._timeout, self._cancel_task)
            return self

        async def __aexit__(self, exc_type, exc_val, exc_tb):
            if exc_type is asyncio.CancelledError and self._cancelled:
                self._unsub = None
                self._task = None
                raise asyncio.TimeoutError
            if self._timeout is not None and self._unsub:
                self._unsub()
                self._unsub = None
            self._task = None
            return None

        @callback
        def _cancel_task(self, now=None):
            if self._task is not None:
                self._task.cancel()
                self._cancelled = True

    monkeypatch.setattr(script, "timeout", MockTimeout)