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