1 from __future__ import annotations 2 3 import sys 4 from collections.abc import Generator 5 from textwrap import dedent 6 from typing import Any 7 8 if sys.version_info < (3, 11): 9 from exceptiongroup import BaseExceptionGroup 10 11 12 class BrokenResourceError(Exception): 13 """ 14 Raised when trying to use a resource that has been rendered unusable due to external 15 causes (e.g. a send stream whose peer has disconnected). 16 """ 17 18 19 class BrokenWorkerProcess(Exception): 20 """ 21 Raised by :meth:`~anyio.to_process.run_sync` if the worker process terminates abruptly or 22 otherwise misbehaves. 23 """ 24 25 26 class BrokenWorkerIntepreter(Exception): 27 """ 28 Raised by :meth:`~anyio.to_interpreter.run_sync` if an unexpected exception is 29 raised in the subinterpreter. 30 """ 31 32 def __init__(self, excinfo: Any): 33 # This was adapted from concurrent.futures.interpreter.ExecutionFailed 34 msg = excinfo.formatted 35 if not msg: 36 if excinfo.type and excinfo.msg: 37 msg = f"{excinfo.type.__name__}: {excinfo.msg}" 38 else: 39 msg = excinfo.type.__name__ or excinfo.msg 40 41 super().__init__(msg) 42 self.excinfo = excinfo 43 44 def __str__(self) -> str: 45 try: 46 formatted = self.excinfo.errdisplay 47 except Exception: 48 return super().__str__() 49 else: 50 return dedent( 51 f""" 52 {super().__str__()} 53 54 Uncaught in the interpreter: 55 56 {formatted} 57 """.strip() 58 ) 59 60 61 class BusyResourceError(Exception): 62 """ 63 Raised when two tasks are trying to read from or write to the same resource 64 concurrently. 65 """ 66 67 def __init__(self, action: str): 68 super().__init__(f"Another task is already {action} this resource") 69 70 71 class ClosedResourceError(Exception): 72 """Raised when trying to use a resource that has been closed.""" 73 74 75 class DelimiterNotFound(Exception): 76 """ 77 Raised during 78 :meth:`~anyio.streams.buffered.BufferedByteReceiveStream.receive_until` if the 79 maximum number of bytes has been read without the delimiter being found. 80 """ 81 82 def __init__(self, max_bytes: int) -> None: 83 super().__init__( 84 f"The delimiter was not found among the first {max_bytes} bytes" 85 ) 86 87 88 class EndOfStream(Exception): 89 """ 90 Raised when trying to read from a stream that has been closed from the other end. 91 """ 92 93 94 class IncompleteRead(Exception): 95 """ 96 Raised during 97 :meth:`~anyio.streams.buffered.BufferedByteReceiveStream.receive_exactly` or 98 :meth:`~anyio.streams.buffered.BufferedByteReceiveStream.receive_until` if the 99 connection is closed before the requested amount of bytes has been read. 100 """ 101 102 def __init__(self) -> None: 103 super().__init__( 104 "The stream was closed before the read operation could be completed" 105 ) 106 107 108 class TypedAttributeLookupError(LookupError): 109 """ 110 Raised by :meth:`~anyio.TypedAttributeProvider.extra` when the given typed attribute 111 is not found and no default value has been given. 112 """ 113 114 115 class WouldBlock(Exception): 116 """Raised by ``X_nowait`` functions if ``X()`` would block.""" 117 118 119 def iterate_exceptions( 120 exception: BaseException, 121 ) -> Generator[BaseException, None, None]: 122 if isinstance(exception, BaseExceptionGroup): 123 for exc in exception.exceptions: 124 yield from iterate_exceptions(exc) 125 else: 126 yield exception 127