1from __future__ import annotations
2
3import sys
4from collections.abc import Generator
5from textwrap import dedent
6from typing import Any
7
8if sys.version_info < (3, 11):
9 from exceptiongroup import BaseExceptionGroup
10
11
12class 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
19class 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
26class BrokenWorkerInterpreter(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
61class 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
71class ClosedResourceError(Exception):
72 """Raised when trying to use a resource that has been closed."""
73
74
75class ConnectionFailed(OSError):
76 """
77 Raised when a connection attempt fails.
78
79 .. note:: This class inherits from :exc:`OSError` for backwards compatibility.
80 """
81
82
83def iterate_exceptions(
84 exception: BaseException,
85) -> Generator[BaseException, None, None]:
86 if isinstance(exception, BaseExceptionGroup):
87 for exc in exception.exceptions:
88 yield from iterate_exceptions(exc)
89 else:
90 yield exception
91
92
93class DelimiterNotFound(Exception):
94 """
95 Raised during
96 :meth:`~anyio.streams.buffered.BufferedByteReceiveStream.receive_until` if the
97 maximum number of bytes has been read without the delimiter being found.
98 """
99
100 def __init__(self, max_bytes: int) -> None:
101 super().__init__(
102 f"The delimiter was not found among the first {max_bytes} bytes"
103 )
104
105
106class EndOfStream(Exception):
107 """
108 Raised when trying to read from a stream that has been closed from the other end.
109 """
110
111
112class IncompleteRead(Exception):
113 """
114 Raised during
115 :meth:`~anyio.streams.buffered.BufferedByteReceiveStream.receive_exactly` or
116 :meth:`~anyio.streams.buffered.BufferedByteReceiveStream.receive_until` if the
117 connection is closed before the requested amount of bytes has been read.
118 """
119
120 def __init__(self) -> None:
121 super().__init__(
122 "The stream was closed before the read operation could be completed"
123 )
124
125
126class TypedAttributeLookupError(LookupError):
127 """
128 Raised by :meth:`~anyio.TypedAttributeProvider.extra` when the given typed attribute
129 is not found and no default value has been given.
130 """
131
132
133class WouldBlock(Exception):
134 """Raised by ``X_nowait`` functions if ``X()`` would block."""