| 216 | raise RuntimeError("generator didn't yield") from None |
| 217 | |
| 218 | async def __aexit__(self, typ, value, traceback): |
| 219 | if typ is None: |
| 220 | try: |
| 221 | await anext(self.gen) |
| 222 | except StopAsyncIteration: |
| 223 | return False |
| 224 | else: |
| 225 | try: |
| 226 | raise RuntimeError("generator didn't stop") |
| 227 | finally: |
| 228 | await self.gen.aclose() |
| 229 | else: |
| 230 | if value is None: |
| 231 | # Need to force instantiation so we can reliably |
| 232 | # tell if we get the same exception back |
| 233 | value = typ() |
| 234 | try: |
| 235 | await self.gen.athrow(value) |
| 236 | except StopAsyncIteration as exc: |
| 237 | # Suppress StopIteration *unless* it's the same exception that |
| 238 | # was passed to throw(). This prevents a StopIteration |
| 239 | # raised inside the "with" statement from being suppressed. |
| 240 | return exc is not value |
| 241 | except RuntimeError as exc: |
| 242 | # Don't re-raise the passed in exception. (issue27122) |
| 243 | if exc is value: |
| 244 | exc.__traceback__ = traceback |
| 245 | return False |
| 246 | # Avoid suppressing if a Stop(Async)Iteration exception |
| 247 | # was passed to athrow() and later wrapped into a RuntimeError |
| 248 | # (see PEP 479 for sync generators; async generators also |
| 249 | # have this behavior). But do this only if the exception wrapped |
| 250 | # by the RuntimeError is actually Stop(Async)Iteration (see |
| 251 | # issue29692). |
| 252 | if ( |
| 253 | isinstance(value, (StopIteration, StopAsyncIteration)) |
| 254 | and exc.__cause__ is value |
| 255 | ): |
| 256 | value.__traceback__ = traceback |
| 257 | return False |
| 258 | raise |
| 259 | except BaseException as exc: |
| 260 | # only re-raise if it's *not* the exception that was |
| 261 | # passed to throw(), because __exit__() must not raise |
| 262 | # an exception unless __exit__() itself failed. But throw() |
| 263 | # has to raise the exception to signal propagation, so this |
| 264 | # fixes the impedance mismatch between the throw() protocol |
| 265 | # and the __exit__() protocol. |
| 266 | if exc is not value: |
| 267 | raise |
| 268 | exc.__traceback__ = traceback |
| 269 | return False |
| 270 | try: |
| 271 | raise RuntimeError("generator didn't stop after athrow()") |
| 272 | finally: |
| 273 | await self.gen.aclose() |
| 274 | |
| 275 | |