Stand-in for the AsyncStream returned by ``events.stream()``. Yields scripted events in order; once exhausted, blocks forever (the real stream stays open until a network event closes it). If ``raise_after`` is set, raises ``raise_with`` after producing that many events — used to exe
| 125 | |
| 126 | |
| 127 | class _FakeStream: |
| 128 | """Stand-in for the AsyncStream returned by ``events.stream()``. |
| 129 | |
| 130 | Yields scripted events in order; once exhausted, blocks forever (the real |
| 131 | stream stays open until a network event closes it). If ``raise_after`` is |
| 132 | set, raises ``raise_with`` after producing that many events — used to |
| 133 | exercise the reconnect-with-backoff path. |
| 134 | """ |
| 135 | |
| 136 | def __init__( |
| 137 | self, |
| 138 | events: list[_StubEvent], |
| 139 | *, |
| 140 | raise_after: int | None = None, |
| 141 | raise_with: BaseException | None = None, |
| 142 | ) -> None: |
| 143 | self._events = events |
| 144 | self._raise_after = raise_after |
| 145 | self._raise_with = raise_with |
| 146 | |
| 147 | async def __aenter__(self) -> _FakeStream: |
| 148 | return self |
| 149 | |
| 150 | async def __aexit__(self, *exc: object) -> None: |
| 151 | return None |
| 152 | |
| 153 | def __aiter__(self) -> Any: |
| 154 | return self._gen() |
| 155 | |
| 156 | async def _gen(self) -> Any: |
| 157 | for i, ev in enumerate(self._events): |
| 158 | yield ev |
| 159 | # Yield control so the dispatch task can pick up the event we just |
| 160 | # produced before we run on to the next one. |
| 161 | await asyncio.sleep(0) |
| 162 | if self._raise_after is not None and i + 1 == self._raise_after: |
| 163 | assert self._raise_with is not None |
| 164 | raise self._raise_with |
| 165 | # Keep the connection "open" until cancelled. |
| 166 | await asyncio.Event().wait() |
| 167 | |
| 168 | |
| 169 | class FakeAsyncEvents: |
no outgoing calls