@ajksunkang-aios/kgraph-linux-x64 0.1.2 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (196) hide show
  1. package/bin/kgraph-launcher +15 -3
  2. package/lib/kgraph/scripts/build-bundle.sh +17 -4
  3. package/lib/site-packages/outcome/__init__.py +20 -0
  4. package/lib/site-packages/outcome/_impl.py +239 -0
  5. package/lib/site-packages/outcome/_util.py +33 -0
  6. package/lib/site-packages/outcome/_version.py +7 -0
  7. package/lib/site-packages/outcome/py.typed +0 -0
  8. package/lib/site-packages/outcome-1.3.0.post0.dist-info/INSTALLER +1 -0
  9. package/lib/site-packages/outcome-1.3.0.post0.dist-info/LICENSE +3 -0
  10. package/lib/site-packages/outcome-1.3.0.post0.dist-info/LICENSE.APACHE2 +202 -0
  11. package/lib/site-packages/outcome-1.3.0.post0.dist-info/LICENSE.MIT +20 -0
  12. package/lib/site-packages/outcome-1.3.0.post0.dist-info/METADATA +63 -0
  13. package/lib/site-packages/outcome-1.3.0.post0.dist-info/RECORD +13 -0
  14. package/lib/site-packages/outcome-1.3.0.post0.dist-info/WHEEL +6 -0
  15. package/lib/site-packages/outcome-1.3.0.post0.dist-info/top_level.txt +1 -0
  16. package/lib/site-packages/sniffio/__init__.py +17 -0
  17. package/lib/site-packages/sniffio/_impl.py +95 -0
  18. package/lib/site-packages/sniffio/_tests/__init__.py +0 -0
  19. package/lib/site-packages/sniffio/_tests/test_sniffio.py +84 -0
  20. package/lib/site-packages/sniffio/_version.py +3 -0
  21. package/lib/site-packages/sniffio/py.typed +0 -0
  22. package/lib/site-packages/sniffio-1.3.1.dist-info/INSTALLER +1 -0
  23. package/lib/site-packages/sniffio-1.3.1.dist-info/LICENSE +3 -0
  24. package/lib/site-packages/sniffio-1.3.1.dist-info/LICENSE.APACHE2 +202 -0
  25. package/lib/site-packages/sniffio-1.3.1.dist-info/LICENSE.MIT +20 -0
  26. package/lib/site-packages/sniffio-1.3.1.dist-info/METADATA +104 -0
  27. package/lib/site-packages/sniffio-1.3.1.dist-info/RECORD +14 -0
  28. package/lib/site-packages/sniffio-1.3.1.dist-info/WHEEL +5 -0
  29. package/lib/site-packages/sniffio-1.3.1.dist-info/top_level.txt +1 -0
  30. package/lib/site-packages/sortedcontainers/__init__.py +74 -0
  31. package/lib/site-packages/sortedcontainers/sorteddict.py +812 -0
  32. package/lib/site-packages/sortedcontainers/sortedlist.py +2646 -0
  33. package/lib/site-packages/sortedcontainers/sortedset.py +733 -0
  34. package/lib/site-packages/sortedcontainers-2.4.0.dist-info/INSTALLER +1 -0
  35. package/lib/site-packages/sortedcontainers-2.4.0.dist-info/LICENSE +13 -0
  36. package/lib/site-packages/sortedcontainers-2.4.0.dist-info/METADATA +264 -0
  37. package/lib/site-packages/sortedcontainers-2.4.0.dist-info/RECORD +10 -0
  38. package/lib/site-packages/sortedcontainers-2.4.0.dist-info/WHEEL +6 -0
  39. package/lib/site-packages/sortedcontainers-2.4.0.dist-info/top_level.txt +1 -0
  40. package/lib/site-packages/trio/__init__.py +133 -0
  41. package/lib/site-packages/trio/__main__.py +3 -0
  42. package/lib/site-packages/trio/_abc.py +714 -0
  43. package/lib/site-packages/trio/_channel.py +610 -0
  44. package/lib/site-packages/trio/_core/__init__.py +94 -0
  45. package/lib/site-packages/trio/_core/_asyncgens.py +243 -0
  46. package/lib/site-packages/trio/_core/_concat_tb.py +26 -0
  47. package/lib/site-packages/trio/_core/_entry_queue.py +223 -0
  48. package/lib/site-packages/trio/_core/_exceptions.py +169 -0
  49. package/lib/site-packages/trio/_core/_generated_instrumentation.py +50 -0
  50. package/lib/site-packages/trio/_core/_generated_io_epoll.py +98 -0
  51. package/lib/site-packages/trio/_core/_generated_io_kqueue.py +153 -0
  52. package/lib/site-packages/trio/_core/_generated_io_windows.py +204 -0
  53. package/lib/site-packages/trio/_core/_generated_run.py +269 -0
  54. package/lib/site-packages/trio/_core/_generated_windows_ffi.py +10 -0
  55. package/lib/site-packages/trio/_core/_instrumentation.py +117 -0
  56. package/lib/site-packages/trio/_core/_io_common.py +31 -0
  57. package/lib/site-packages/trio/_core/_io_epoll.py +385 -0
  58. package/lib/site-packages/trio/_core/_io_kqueue.py +292 -0
  59. package/lib/site-packages/trio/_core/_io_windows.py +1036 -0
  60. package/lib/site-packages/trio/_core/_ki.py +271 -0
  61. package/lib/site-packages/trio/_core/_local.py +104 -0
  62. package/lib/site-packages/trio/_core/_mock_clock.py +165 -0
  63. package/lib/site-packages/trio/_core/_parking_lot.py +317 -0
  64. package/lib/site-packages/trio/_core/_run.py +3148 -0
  65. package/lib/site-packages/trio/_core/_run_context.py +15 -0
  66. package/lib/site-packages/trio/_core/_tests/__init__.py +0 -0
  67. package/lib/site-packages/trio/_core/_tests/test_asyncgen.py +339 -0
  68. package/lib/site-packages/trio/_core/_tests/test_cancelled.py +222 -0
  69. package/lib/site-packages/trio/_core/_tests/test_exceptiongroup_gc.py +103 -0
  70. package/lib/site-packages/trio/_core/_tests/test_guest_mode.py +755 -0
  71. package/lib/site-packages/trio/_core/_tests/test_instrumentation.py +315 -0
  72. package/lib/site-packages/trio/_core/_tests/test_io.py +522 -0
  73. package/lib/site-packages/trio/_core/_tests/test_ki.py +703 -0
  74. package/lib/site-packages/trio/_core/_tests/test_local.py +118 -0
  75. package/lib/site-packages/trio/_core/_tests/test_mock_clock.py +193 -0
  76. package/lib/site-packages/trio/_core/_tests/test_parking_lot.py +389 -0
  77. package/lib/site-packages/trio/_core/_tests/test_run.py +3024 -0
  78. package/lib/site-packages/trio/_core/_tests/test_thread_cache.py +227 -0
  79. package/lib/site-packages/trio/_core/_tests/test_tutil.py +13 -0
  80. package/lib/site-packages/trio/_core/_tests/test_unbounded_queue.py +154 -0
  81. package/lib/site-packages/trio/_core/_tests/test_windows.py +305 -0
  82. package/lib/site-packages/trio/_core/_tests/tutil.py +117 -0
  83. package/lib/site-packages/trio/_core/_tests/type_tests/nursery_start.py +79 -0
  84. package/lib/site-packages/trio/_core/_tests/type_tests/run.py +51 -0
  85. package/lib/site-packages/trio/_core/_thread_cache.py +317 -0
  86. package/lib/site-packages/trio/_core/_traps.py +318 -0
  87. package/lib/site-packages/trio/_core/_unbounded_queue.py +163 -0
  88. package/lib/site-packages/trio/_core/_wakeup_socketpair.py +75 -0
  89. package/lib/site-packages/trio/_core/_windows_cffi.py +313 -0
  90. package/lib/site-packages/trio/_deprecate.py +171 -0
  91. package/lib/site-packages/trio/_dtls.py +1380 -0
  92. package/lib/site-packages/trio/_file_io.py +513 -0
  93. package/lib/site-packages/trio/_highlevel_generic.py +125 -0
  94. package/lib/site-packages/trio/_highlevel_open_tcp_listeners.py +251 -0
  95. package/lib/site-packages/trio/_highlevel_open_tcp_stream.py +397 -0
  96. package/lib/site-packages/trio/_highlevel_open_unix_stream.py +65 -0
  97. package/lib/site-packages/trio/_highlevel_serve_listeners.py +148 -0
  98. package/lib/site-packages/trio/_highlevel_socket.py +423 -0
  99. package/lib/site-packages/trio/_highlevel_ssl_helpers.py +180 -0
  100. package/lib/site-packages/trio/_path.py +289 -0
  101. package/lib/site-packages/trio/_repl.py +159 -0
  102. package/lib/site-packages/trio/_signals.py +185 -0
  103. package/lib/site-packages/trio/_socket.py +1326 -0
  104. package/lib/site-packages/trio/_ssl.py +964 -0
  105. package/lib/site-packages/trio/_subprocess.py +1178 -0
  106. package/lib/site-packages/trio/_subprocess_platform/__init__.py +123 -0
  107. package/lib/site-packages/trio/_subprocess_platform/kqueue.py +48 -0
  108. package/lib/site-packages/trio/_subprocess_platform/waitid.py +113 -0
  109. package/lib/site-packages/trio/_subprocess_platform/windows.py +11 -0
  110. package/lib/site-packages/trio/_sync.py +908 -0
  111. package/lib/site-packages/trio/_tests/__init__.py +0 -0
  112. package/lib/site-packages/trio/_tests/astrill-codesigning-cert.cer +0 -0
  113. package/lib/site-packages/trio/_tests/check_type_completeness.py +247 -0
  114. package/lib/site-packages/trio/_tests/module_with_deprecations.py +22 -0
  115. package/lib/site-packages/trio/_tests/pytest_plugin.py +54 -0
  116. package/lib/site-packages/trio/_tests/test_abc.py +72 -0
  117. package/lib/site-packages/trio/_tests/test_channel.py +750 -0
  118. package/lib/site-packages/trio/_tests/test_contextvars.py +56 -0
  119. package/lib/site-packages/trio/_tests/test_deprecate.py +277 -0
  120. package/lib/site-packages/trio/_tests/test_deprecate_strict_exception_groups_false.py +64 -0
  121. package/lib/site-packages/trio/_tests/test_dtls.py +950 -0
  122. package/lib/site-packages/trio/_tests/test_exports.py +626 -0
  123. package/lib/site-packages/trio/_tests/test_fakenet.py +317 -0
  124. package/lib/site-packages/trio/_tests/test_file_io.py +269 -0
  125. package/lib/site-packages/trio/_tests/test_highlevel_generic.py +98 -0
  126. package/lib/site-packages/trio/_tests/test_highlevel_open_tcp_listeners.py +419 -0
  127. package/lib/site-packages/trio/_tests/test_highlevel_open_tcp_stream.py +693 -0
  128. package/lib/site-packages/trio/_tests/test_highlevel_open_unix_stream.py +86 -0
  129. package/lib/site-packages/trio/_tests/test_highlevel_serve_listeners.py +186 -0
  130. package/lib/site-packages/trio/_tests/test_highlevel_socket.py +336 -0
  131. package/lib/site-packages/trio/_tests/test_highlevel_ssl_helpers.py +169 -0
  132. package/lib/site-packages/trio/_tests/test_path.py +279 -0
  133. package/lib/site-packages/trio/_tests/test_repl.py +428 -0
  134. package/lib/site-packages/trio/_tests/test_scheduler_determinism.py +47 -0
  135. package/lib/site-packages/trio/_tests/test_signals.py +186 -0
  136. package/lib/site-packages/trio/_tests/test_socket.py +1253 -0
  137. package/lib/site-packages/trio/_tests/test_ssl.py +1371 -0
  138. package/lib/site-packages/trio/_tests/test_subprocess.py +767 -0
  139. package/lib/site-packages/trio/_tests/test_sync.py +735 -0
  140. package/lib/site-packages/trio/_tests/test_testing.py +682 -0
  141. package/lib/site-packages/trio/_tests/test_testing_raisesgroup.py +1128 -0
  142. package/lib/site-packages/trio/_tests/test_threads.py +1173 -0
  143. package/lib/site-packages/trio/_tests/test_timeouts.py +281 -0
  144. package/lib/site-packages/trio/_tests/test_tracing.py +88 -0
  145. package/lib/site-packages/trio/_tests/test_trio.py +8 -0
  146. package/lib/site-packages/trio/_tests/test_unix_pipes.py +288 -0
  147. package/lib/site-packages/trio/_tests/test_util.py +349 -0
  148. package/lib/site-packages/trio/_tests/test_wait_for_object.py +225 -0
  149. package/lib/site-packages/trio/_tests/test_windows_pipes.py +112 -0
  150. package/lib/site-packages/trio/_tests/tools/__init__.py +0 -0
  151. package/lib/site-packages/trio/_tests/tools/test_gen_exports.py +179 -0
  152. package/lib/site-packages/trio/_tests/tools/test_mypy_annotate.py +140 -0
  153. package/lib/site-packages/trio/_tests/tools/test_sync_requirements.py +80 -0
  154. package/lib/site-packages/trio/_tests/type_tests/check_wraps.py +9 -0
  155. package/lib/site-packages/trio/_tests/type_tests/open_memory_channel.py +4 -0
  156. package/lib/site-packages/trio/_tests/type_tests/path.py +140 -0
  157. package/lib/site-packages/trio/_tests/type_tests/subprocesses.py +23 -0
  158. package/lib/site-packages/trio/_tests/type_tests/task_status.py +29 -0
  159. package/lib/site-packages/trio/_threads.py +610 -0
  160. package/lib/site-packages/trio/_timeouts.py +197 -0
  161. package/lib/site-packages/trio/_tools/__init__.py +0 -0
  162. package/lib/site-packages/trio/_tools/gen_exports.py +401 -0
  163. package/lib/site-packages/trio/_tools/mypy_annotate.py +126 -0
  164. package/lib/site-packages/trio/_tools/sync_requirements.py +98 -0
  165. package/lib/site-packages/trio/_tools/windows_ffi_build.py +220 -0
  166. package/lib/site-packages/trio/_unix_pipes.py +197 -0
  167. package/lib/site-packages/trio/_util.py +385 -0
  168. package/lib/site-packages/trio/_version.py +3 -0
  169. package/lib/site-packages/trio/_wait_for_object.py +67 -0
  170. package/lib/site-packages/trio/_windows_pipes.py +144 -0
  171. package/lib/site-packages/trio/abc.py +23 -0
  172. package/lib/site-packages/trio/from_thread.py +13 -0
  173. package/lib/site-packages/trio/lowlevel.py +95 -0
  174. package/lib/site-packages/trio/py.typed +0 -0
  175. package/lib/site-packages/trio/socket.py +602 -0
  176. package/lib/site-packages/trio/testing/__init__.py +58 -0
  177. package/lib/site-packages/trio/testing/_check_streams.py +570 -0
  178. package/lib/site-packages/trio/testing/_checkpoints.py +69 -0
  179. package/lib/site-packages/trio/testing/_fake_net.py +584 -0
  180. package/lib/site-packages/trio/testing/_memory_streams.py +633 -0
  181. package/lib/site-packages/trio/testing/_network.py +36 -0
  182. package/lib/site-packages/trio/testing/_raises_group.py +1015 -0
  183. package/lib/site-packages/trio/testing/_sequencer.py +87 -0
  184. package/lib/site-packages/trio/testing/_trio_test.py +50 -0
  185. package/lib/site-packages/trio/to_thread.py +4 -0
  186. package/lib/site-packages/trio-0.33.0.dist-info/INSTALLER +1 -0
  187. package/lib/site-packages/trio-0.33.0.dist-info/METADATA +186 -0
  188. package/lib/site-packages/trio-0.33.0.dist-info/RECORD +156 -0
  189. package/lib/site-packages/trio-0.33.0.dist-info/REQUESTED +0 -0
  190. package/lib/site-packages/trio-0.33.0.dist-info/WHEEL +5 -0
  191. package/lib/site-packages/trio-0.33.0.dist-info/entry_points.txt +2 -0
  192. package/lib/site-packages/trio-0.33.0.dist-info/licenses/LICENSE +3 -0
  193. package/lib/site-packages/trio-0.33.0.dist-info/licenses/LICENSE.APACHE2 +202 -0
  194. package/lib/site-packages/trio-0.33.0.dist-info/licenses/LICENSE.MIT +22 -0
  195. package/lib/site-packages/trio-0.33.0.dist-info/top_level.txt +1 -0
  196. package/package.json +1 -1
@@ -0,0 +1,513 @@
1
+ from __future__ import annotations
2
+
3
+ import io
4
+ from collections.abc import Callable, Iterable
5
+ from functools import partial
6
+ from typing import (
7
+ IO,
8
+ TYPE_CHECKING,
9
+ Any,
10
+ AnyStr,
11
+ BinaryIO,
12
+ Generic,
13
+ Literal,
14
+ TypeVar,
15
+ Union,
16
+ overload,
17
+ )
18
+
19
+ import trio
20
+
21
+ from ._util import async_wraps
22
+ from .abc import AsyncResource
23
+
24
+ if TYPE_CHECKING:
25
+ from _typeshed import (
26
+ OpenBinaryMode,
27
+ OpenBinaryModeReading,
28
+ OpenBinaryModeUpdating,
29
+ OpenBinaryModeWriting,
30
+ OpenTextMode,
31
+ StrOrBytesPath,
32
+ )
33
+
34
+ from ._sync import CapacityLimiter
35
+
36
+ # This list is also in the docs, make sure to keep them in sync
37
+ _FILE_SYNC_ATTRS: set[str] = {
38
+ "closed",
39
+ "encoding",
40
+ "errors",
41
+ "fileno",
42
+ "isatty",
43
+ "newlines",
44
+ "readable",
45
+ "seekable",
46
+ "writable",
47
+ # not defined in *IOBase:
48
+ "buffer",
49
+ "raw",
50
+ "line_buffering",
51
+ "closefd",
52
+ "name",
53
+ "mode",
54
+ "getvalue",
55
+ "getbuffer",
56
+ }
57
+
58
+ # This list is also in the docs, make sure to keep them in sync
59
+ _FILE_ASYNC_METHODS: set[str] = {
60
+ "flush",
61
+ "read",
62
+ "read1",
63
+ "readall",
64
+ "readinto",
65
+ "readline",
66
+ "readlines",
67
+ "seek",
68
+ "tell",
69
+ "truncate",
70
+ "write",
71
+ "writelines",
72
+ # not defined in *IOBase:
73
+ "readinto1",
74
+ "peek",
75
+ }
76
+
77
+
78
+ FileT = TypeVar("FileT")
79
+ FileT_co = TypeVar("FileT_co", covariant=True)
80
+ T = TypeVar("T")
81
+ T_co = TypeVar("T_co", covariant=True)
82
+ T_contra = TypeVar("T_contra", contravariant=True)
83
+ AnyStr_co = TypeVar("AnyStr_co", str, bytes, covariant=True)
84
+ AnyStr_contra = TypeVar("AnyStr_contra", str, bytes, contravariant=True)
85
+
86
+ # This is a little complicated. IO objects have a lot of methods, and which are available on
87
+ # different types varies wildly. We want to match the interface of whatever file we're wrapping.
88
+ # This pile of protocols each has one sync method/property, meaning they're going to be compatible
89
+ # with a file class that supports that method/property. The ones parameterized with AnyStr take
90
+ # either str or bytes depending.
91
+
92
+ # The wrapper is then a generic class, where the typevar is set to the type of the sync file we're
93
+ # wrapping. For generics, adding a type to self has a special meaning - properties/methods can be
94
+ # conditional - it's only valid to call them if the object you're accessing them on is compatible
95
+ # with that type hint. By using the protocols, the type checker will be checking to see if the
96
+ # wrapped type has that method, and only allow the methods that do to be called. We can then alter
97
+ # the signature however it needs to match runtime behaviour.
98
+ # More info: https://mypy.readthedocs.io/en/stable/more_types.html#advanced-uses-of-self-types
99
+ if TYPE_CHECKING:
100
+ from typing_extensions import Buffer, Protocol
101
+
102
+ # fmt: off
103
+
104
+ class _HasClosed(Protocol):
105
+ @property
106
+ def closed(self) -> bool: ...
107
+
108
+ class _HasEncoding(Protocol):
109
+ @property
110
+ def encoding(self) -> str: ...
111
+
112
+ class _HasErrors(Protocol):
113
+ @property
114
+ def errors(self) -> str | None: ...
115
+
116
+ class _HasFileNo(Protocol):
117
+ def fileno(self) -> int: ...
118
+
119
+ class _HasIsATTY(Protocol):
120
+ def isatty(self) -> bool: ...
121
+
122
+ class _HasNewlines(Protocol[T_co]):
123
+ # Type varies here - documented to be None, tuple of strings, strings. Typeshed uses Any.
124
+ @property
125
+ def newlines(self) -> T_co: ...
126
+
127
+ class _HasReadable(Protocol):
128
+ def readable(self) -> bool: ...
129
+
130
+ class _HasSeekable(Protocol):
131
+ def seekable(self) -> bool: ...
132
+
133
+ class _HasWritable(Protocol):
134
+ def writable(self) -> bool: ...
135
+
136
+ class _HasBuffer(Protocol):
137
+ @property
138
+ def buffer(self) -> BinaryIO: ...
139
+
140
+ class _HasRaw(Protocol):
141
+ @property
142
+ def raw(self) -> io.RawIOBase: ...
143
+
144
+ class _HasLineBuffering(Protocol):
145
+ @property
146
+ def line_buffering(self) -> bool: ...
147
+
148
+ class _HasCloseFD(Protocol):
149
+ @property
150
+ def closefd(self) -> bool: ...
151
+
152
+ class _HasName(Protocol):
153
+ @property
154
+ def name(self) -> str: ...
155
+
156
+ class _HasMode(Protocol):
157
+ @property
158
+ def mode(self) -> str: ...
159
+
160
+ class _CanGetValue(Protocol[AnyStr_co]):
161
+ def getvalue(self) -> AnyStr_co: ...
162
+
163
+ class _CanGetBuffer(Protocol):
164
+ def getbuffer(self) -> memoryview: ...
165
+
166
+ class _CanFlush(Protocol):
167
+ def flush(self) -> None: ...
168
+
169
+ class _CanRead(Protocol[AnyStr_co]):
170
+ def read(self, size: int | None = ..., /) -> AnyStr_co: ...
171
+
172
+ class _CanRead1(Protocol):
173
+ def read1(self, size: int | None = ..., /) -> bytes: ...
174
+
175
+ class _CanReadAll(Protocol[AnyStr_co]):
176
+ def readall(self) -> AnyStr_co: ...
177
+
178
+ class _CanReadInto(Protocol):
179
+ def readinto(self, buf: Buffer, /) -> int | None: ...
180
+
181
+ class _CanReadInto1(Protocol):
182
+ def readinto1(self, buffer: Buffer, /) -> int: ...
183
+
184
+ class _CanReadLine(Protocol[AnyStr_co]):
185
+ def readline(self, size: int = ..., /) -> AnyStr_co: ...
186
+
187
+ class _CanReadLines(Protocol[AnyStr]):
188
+ def readlines(self, hint: int = ..., /) -> list[AnyStr]: ...
189
+
190
+ class _CanSeek(Protocol):
191
+ def seek(self, target: int, whence: int = 0, /) -> int: ...
192
+
193
+ class _CanTell(Protocol):
194
+ def tell(self) -> int: ...
195
+
196
+ class _CanTruncate(Protocol):
197
+ def truncate(self, size: int | None = ..., /) -> int: ...
198
+
199
+ class _CanWrite(Protocol[T_contra]):
200
+ def write(self, data: T_contra, /) -> int: ...
201
+
202
+ class _CanWriteLines(Protocol[T_contra]):
203
+ # The lines parameter varies for bytes/str, so use a typevar to make the async match.
204
+ def writelines(self, lines: Iterable[T_contra], /) -> None: ...
205
+
206
+ class _CanPeek(Protocol[AnyStr_co]):
207
+ def peek(self, size: int = 0, /) -> AnyStr_co: ...
208
+
209
+ class _CanDetach(Protocol[T_co]):
210
+ # The T typevar will be the unbuffered/binary file this file wraps.
211
+ def detach(self) -> T_co: ...
212
+
213
+ class _CanClose(Protocol):
214
+ def close(self) -> None: ...
215
+
216
+
217
+ # FileT needs to be covariant for the protocol trick to work - the real IO types are effectively a
218
+ # subtype of the protocols.
219
+ class AsyncIOWrapper(AsyncResource, Generic[FileT_co]):
220
+ """A generic :class:`~io.IOBase` wrapper that implements the :term:`asynchronous
221
+ file object` interface. Wrapped methods that could block are executed in
222
+ :meth:`trio.to_thread.run_sync`.
223
+
224
+ All properties and methods defined in :mod:`~io` are exposed by this
225
+ wrapper, if they exist in the wrapped file object.
226
+ """
227
+
228
+ def __init__(self, file: FileT_co) -> None:
229
+ self._wrapped = file
230
+
231
+ @property
232
+ def wrapped(self) -> FileT_co:
233
+ """object: A reference to the wrapped file object"""
234
+
235
+ return self._wrapped
236
+
237
+ if not TYPE_CHECKING:
238
+
239
+ def __getattr__(self, name: str) -> object:
240
+ if name in _FILE_SYNC_ATTRS:
241
+ return getattr(self._wrapped, name)
242
+ if name in _FILE_ASYNC_METHODS:
243
+ meth = getattr(self._wrapped, name)
244
+
245
+ @async_wraps(self.__class__, self._wrapped.__class__, name)
246
+ async def wrapper(
247
+ *args: Callable[..., T],
248
+ **kwargs: object | str | bool | CapacityLimiter | None,
249
+ ) -> T:
250
+ func = partial(meth, *args, **kwargs)
251
+ return await trio.to_thread.run_sync(func)
252
+
253
+ # cache the generated method
254
+ setattr(self, name, wrapper)
255
+ return wrapper
256
+
257
+ raise AttributeError(name)
258
+
259
+ def __dir__(self) -> Iterable[str]:
260
+ attrs = set(super().__dir__())
261
+ attrs.update(a for a in _FILE_SYNC_ATTRS if hasattr(self.wrapped, a))
262
+ attrs.update(a for a in _FILE_ASYNC_METHODS if hasattr(self.wrapped, a))
263
+ return attrs
264
+
265
+ def __aiter__(self) -> AsyncIOWrapper[FileT_co]:
266
+ return self
267
+
268
+ async def __anext__(self: AsyncIOWrapper[_CanReadLine[AnyStr]]) -> AnyStr:
269
+ line = await self.readline()
270
+ if line:
271
+ return line
272
+ else:
273
+ raise StopAsyncIteration
274
+
275
+ async def detach(self: AsyncIOWrapper[_CanDetach[T]]) -> AsyncIOWrapper[T]:
276
+ """Like :meth:`io.BufferedIOBase.detach`, but async.
277
+
278
+ This also re-wraps the result in a new :term:`asynchronous file object`
279
+ wrapper.
280
+
281
+ """
282
+
283
+ raw = await trio.to_thread.run_sync(self._wrapped.detach)
284
+ return wrap_file(raw)
285
+
286
+ async def aclose(self: AsyncIOWrapper[_CanClose]) -> None:
287
+ """Like :meth:`io.IOBase.close`, but async.
288
+
289
+ This is also shielded from cancellation; if a cancellation scope is
290
+ cancelled, the wrapped file object will still be safely closed.
291
+
292
+ """
293
+
294
+ # ensure the underling file is closed during cancellation
295
+ with trio.CancelScope(shield=True):
296
+ await trio.to_thread.run_sync(self._wrapped.close)
297
+
298
+ await trio.lowlevel.checkpoint_if_cancelled()
299
+
300
+ if TYPE_CHECKING:
301
+ # fmt: off
302
+ # Based on typing.IO and io stubs.
303
+ @property
304
+ def closed(self: AsyncIOWrapper[_HasClosed]) -> bool: ...
305
+ @property
306
+ def encoding(self: AsyncIOWrapper[_HasEncoding]) -> str: ...
307
+ @property
308
+ def errors(self: AsyncIOWrapper[_HasErrors]) -> str | None: ...
309
+ @property
310
+ def newlines(self: AsyncIOWrapper[_HasNewlines[T]]) -> T: ...
311
+ @property
312
+ def buffer(self: AsyncIOWrapper[_HasBuffer]) -> BinaryIO: ...
313
+ @property
314
+ def raw(self: AsyncIOWrapper[_HasRaw]) -> io.RawIOBase: ...
315
+ @property
316
+ def line_buffering(self: AsyncIOWrapper[_HasLineBuffering]) -> int: ...
317
+ @property
318
+ def closefd(self: AsyncIOWrapper[_HasCloseFD]) -> bool: ...
319
+ @property
320
+ def name(self: AsyncIOWrapper[_HasName]) -> str: ...
321
+ @property
322
+ def mode(self: AsyncIOWrapper[_HasMode]) -> str: ...
323
+
324
+ def fileno(self: AsyncIOWrapper[_HasFileNo]) -> int: ...
325
+ def isatty(self: AsyncIOWrapper[_HasIsATTY]) -> bool: ...
326
+ def readable(self: AsyncIOWrapper[_HasReadable]) -> bool: ...
327
+ def seekable(self: AsyncIOWrapper[_HasSeekable]) -> bool: ...
328
+ def writable(self: AsyncIOWrapper[_HasWritable]) -> bool: ...
329
+ def getvalue(self: AsyncIOWrapper[_CanGetValue[AnyStr]]) -> AnyStr: ...
330
+ def getbuffer(self: AsyncIOWrapper[_CanGetBuffer]) -> memoryview: ...
331
+ async def flush(self: AsyncIOWrapper[_CanFlush]) -> None: ...
332
+ async def read(self: AsyncIOWrapper[_CanRead[AnyStr]], size: int | None = -1, /) -> AnyStr: ...
333
+ async def read1(self: AsyncIOWrapper[_CanRead1], size: int | None = -1, /) -> bytes: ...
334
+ async def readall(self: AsyncIOWrapper[_CanReadAll[AnyStr]]) -> AnyStr: ...
335
+ async def readinto(self: AsyncIOWrapper[_CanReadInto], buf: Buffer, /) -> int | None: ...
336
+ async def readline(self: AsyncIOWrapper[_CanReadLine[AnyStr]], size: int = -1, /) -> AnyStr: ...
337
+ async def readlines(self: AsyncIOWrapper[_CanReadLines[AnyStr]]) -> list[AnyStr]: ...
338
+ async def seek(self: AsyncIOWrapper[_CanSeek], target: int, whence: int = 0, /) -> int: ...
339
+ async def tell(self: AsyncIOWrapper[_CanTell]) -> int: ...
340
+ async def truncate(self: AsyncIOWrapper[_CanTruncate], size: int | None = None, /) -> int: ...
341
+ async def write(self: AsyncIOWrapper[_CanWrite[T]], data: T, /) -> int: ...
342
+ async def writelines(self: AsyncIOWrapper[_CanWriteLines[T]], lines: Iterable[T], /) -> None: ...
343
+ async def readinto1(self: AsyncIOWrapper[_CanReadInto1], buffer: Buffer, /) -> int: ...
344
+ async def peek(self: AsyncIOWrapper[_CanPeek[AnyStr]], size: int = 0, /) -> AnyStr: ...
345
+
346
+
347
+ # Type hints are copied from builtin open.
348
+ _OpenFile = Union["StrOrBytesPath", int]
349
+ _Opener = Callable[[str, int], int]
350
+
351
+
352
+ @overload
353
+ async def open_file(
354
+ file: _OpenFile,
355
+ mode: OpenTextMode = "r",
356
+ buffering: int = -1,
357
+ encoding: str | None = None,
358
+ errors: str | None = None,
359
+ newline: str | None = None,
360
+ closefd: bool = True,
361
+ opener: _Opener | None = None,
362
+ ) -> AsyncIOWrapper[io.TextIOWrapper]: ...
363
+
364
+
365
+ @overload
366
+ async def open_file(
367
+ file: _OpenFile,
368
+ mode: OpenBinaryMode,
369
+ buffering: Literal[0],
370
+ encoding: None = None,
371
+ errors: None = None,
372
+ newline: None = None,
373
+ closefd: bool = True,
374
+ opener: _Opener | None = None,
375
+ ) -> AsyncIOWrapper[io.FileIO]: ...
376
+
377
+
378
+ @overload
379
+ async def open_file(
380
+ file: _OpenFile,
381
+ mode: OpenBinaryModeUpdating,
382
+ buffering: Literal[-1, 1] = -1,
383
+ encoding: None = None,
384
+ errors: None = None,
385
+ newline: None = None,
386
+ closefd: bool = True,
387
+ opener: _Opener | None = None,
388
+ ) -> AsyncIOWrapper[io.BufferedRandom]: ...
389
+
390
+
391
+ @overload
392
+ async def open_file(
393
+ file: _OpenFile,
394
+ mode: OpenBinaryModeWriting,
395
+ buffering: Literal[-1, 1] = -1,
396
+ encoding: None = None,
397
+ errors: None = None,
398
+ newline: None = None,
399
+ closefd: bool = True,
400
+ opener: _Opener | None = None,
401
+ ) -> AsyncIOWrapper[io.BufferedWriter]: ...
402
+
403
+
404
+ @overload
405
+ async def open_file(
406
+ file: _OpenFile,
407
+ mode: OpenBinaryModeReading,
408
+ buffering: Literal[-1, 1] = -1,
409
+ encoding: None = None,
410
+ errors: None = None,
411
+ newline: None = None,
412
+ closefd: bool = True,
413
+ opener: _Opener | None = None,
414
+ ) -> AsyncIOWrapper[io.BufferedReader]: ...
415
+
416
+
417
+ @overload
418
+ async def open_file(
419
+ file: _OpenFile,
420
+ mode: OpenBinaryMode,
421
+ buffering: int,
422
+ encoding: None = None,
423
+ errors: None = None,
424
+ newline: None = None,
425
+ closefd: bool = True,
426
+ opener: _Opener | None = None,
427
+ ) -> AsyncIOWrapper[BinaryIO]: ...
428
+
429
+
430
+ @overload
431
+ async def open_file( # type: ignore[explicit-any] # Any usage matches builtins.open().
432
+ file: _OpenFile,
433
+ mode: str,
434
+ buffering: int = -1,
435
+ encoding: str | None = None,
436
+ errors: str | None = None,
437
+ newline: str | None = None,
438
+ closefd: bool = True,
439
+ opener: _Opener | None = None,
440
+ ) -> AsyncIOWrapper[IO[Any]]: ...
441
+
442
+
443
+ async def open_file(
444
+ file: _OpenFile,
445
+ mode: str = "r",
446
+ buffering: int = -1,
447
+ encoding: str | None = None,
448
+ errors: str | None = None,
449
+ newline: str | None = None,
450
+ closefd: bool = True,
451
+ opener: _Opener | None = None,
452
+ ) -> AsyncIOWrapper[object]:
453
+ """Asynchronous version of :func:`open`.
454
+
455
+ Returns:
456
+ An :term:`asynchronous file object`
457
+
458
+ Example::
459
+
460
+ async with await trio.open_file(filename) as f:
461
+ async for line in f:
462
+ pass
463
+
464
+ assert f.closed
465
+
466
+ See also:
467
+ :func:`trio.Path.open`
468
+
469
+ """
470
+ file_ = wrap_file(
471
+ await trio.to_thread.run_sync(
472
+ io.open,
473
+ file,
474
+ mode,
475
+ buffering,
476
+ encoding,
477
+ errors,
478
+ newline,
479
+ closefd,
480
+ opener,
481
+ ),
482
+ )
483
+ return file_
484
+
485
+
486
+ def wrap_file(file: FileT) -> AsyncIOWrapper[FileT]:
487
+ """This wraps any file object in a wrapper that provides an asynchronous
488
+ file object interface.
489
+
490
+ Args:
491
+ file: a :term:`file object`
492
+
493
+ Returns:
494
+ An :term:`asynchronous file object` that wraps ``file``
495
+
496
+ Example::
497
+
498
+ async_file = trio.wrap_file(StringIO('asdf'))
499
+
500
+ assert await async_file.read() == 'asdf'
501
+
502
+ """
503
+
504
+ def has(attr: str) -> bool:
505
+ return hasattr(file, attr) and callable(getattr(file, attr))
506
+
507
+ if not (has("close") and (has("read") or has("write"))):
508
+ raise TypeError(
509
+ f"{file} does not implement required duck-file methods: "
510
+ "close and (read or write)",
511
+ )
512
+
513
+ return AsyncIOWrapper(file)
@@ -0,0 +1,125 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import Generic, TypeGuard, TypeVar
4
+
5
+ import attrs
6
+
7
+ import trio
8
+ from trio._util import final
9
+
10
+ from .abc import AsyncResource, HalfCloseableStream, ReceiveStream, SendStream
11
+
12
+ SendStreamT = TypeVar("SendStreamT", bound=SendStream)
13
+ ReceiveStreamT = TypeVar("ReceiveStreamT", bound=ReceiveStream)
14
+
15
+
16
+ async def aclose_forcefully(resource: AsyncResource) -> None:
17
+ """Close an async resource or async generator immediately, without
18
+ blocking to do any graceful cleanup.
19
+
20
+ :class:`~trio.abc.AsyncResource` objects guarantee that if their
21
+ :meth:`~trio.abc.AsyncResource.aclose` method is cancelled, then they will
22
+ still close the resource (albeit in a potentially ungraceful
23
+ fashion). :func:`aclose_forcefully` is a convenience function that
24
+ exploits this behavior to let you force a resource to be closed without
25
+ blocking: it works by calling ``await resource.aclose()`` and then
26
+ cancelling it immediately.
27
+
28
+ Most users won't need this, but it may be useful on cleanup paths where
29
+ you can't afford to block, or if you want to close a resource and don't
30
+ care about handling it gracefully. For example, if
31
+ :class:`~trio.SSLStream` encounters an error and cannot perform its
32
+ own graceful close, then there's no point in waiting to gracefully shut
33
+ down the underlying transport either, so it calls ``await
34
+ aclose_forcefully(self.transport_stream)``.
35
+
36
+ Note that this function is async, and that it acts as a checkpoint, but
37
+ unlike most async functions it cannot block indefinitely (at least,
38
+ assuming the underlying resource object is correctly implemented).
39
+
40
+ """
41
+ with trio.CancelScope() as cs:
42
+ cs.cancel(reason="cancelled during aclose_forcefully")
43
+ await resource.aclose()
44
+
45
+
46
+ def _is_halfclosable(stream: SendStream) -> TypeGuard[HalfCloseableStream]:
47
+ """Check if the stream has a send_eof() method."""
48
+ return hasattr(stream, "send_eof")
49
+
50
+
51
+ @final
52
+ @attrs.define(eq=False, slots=False)
53
+ class StapledStream(
54
+ HalfCloseableStream,
55
+ Generic[SendStreamT, ReceiveStreamT],
56
+ ):
57
+ """This class `staples <https://en.wikipedia.org/wiki/Staple_(fastener)>`__
58
+ together two unidirectional streams to make single bidirectional stream.
59
+
60
+ Args:
61
+ send_stream (~trio.abc.SendStream): The stream to use for sending.
62
+ receive_stream (~trio.abc.ReceiveStream): The stream to use for
63
+ receiving.
64
+
65
+ Example:
66
+
67
+ A silly way to make a stream that echoes back whatever you write to
68
+ it::
69
+
70
+ left, right = trio.testing.memory_stream_pair()
71
+ echo_stream = StapledStream(SocketStream(left), SocketStream(right))
72
+ await echo_stream.send_all(b"x")
73
+ assert await echo_stream.receive_some() == b"x"
74
+
75
+ :class:`StapledStream` objects implement the methods in the
76
+ :class:`~trio.abc.HalfCloseableStream` interface. They also have two
77
+ additional public attributes:
78
+
79
+ .. attribute:: send_stream
80
+
81
+ The underlying :class:`~trio.abc.SendStream`. :meth:`send_all` and
82
+ :meth:`wait_send_all_might_not_block` are delegated to this object.
83
+
84
+ .. attribute:: receive_stream
85
+
86
+ The underlying :class:`~trio.abc.ReceiveStream`. :meth:`receive_some`
87
+ is delegated to this object.
88
+
89
+ """
90
+
91
+ send_stream: SendStreamT
92
+ receive_stream: ReceiveStreamT
93
+
94
+ async def send_all(self, data: bytes | bytearray | memoryview) -> None:
95
+ """Calls ``self.send_stream.send_all``."""
96
+ return await self.send_stream.send_all(data)
97
+
98
+ async def wait_send_all_might_not_block(self) -> None:
99
+ """Calls ``self.send_stream.wait_send_all_might_not_block``."""
100
+ return await self.send_stream.wait_send_all_might_not_block()
101
+
102
+ async def send_eof(self) -> None:
103
+ """Shuts down the send side of the stream.
104
+
105
+ If :meth:`self.send_stream.send_eof() <trio.abc.HalfCloseableStream.send_eof>` exists,
106
+ then this calls it. Otherwise, this calls
107
+ :meth:`self.send_stream.aclose() <trio.abc.AsyncResource.aclose>`.
108
+ """
109
+ stream = self.send_stream
110
+ if _is_halfclosable(stream):
111
+ return await stream.send_eof()
112
+ else:
113
+ return await stream.aclose()
114
+
115
+ # we intentionally accept more types from the caller than we support returning
116
+ async def receive_some(self, max_bytes: int | None = None) -> bytes:
117
+ """Calls ``self.receive_stream.receive_some``."""
118
+ return await self.receive_stream.receive_some(max_bytes)
119
+
120
+ async def aclose(self) -> None:
121
+ """Calls ``aclose`` on both underlying streams."""
122
+ try:
123
+ await self.send_stream.aclose()
124
+ finally:
125
+ await self.receive_stream.aclose()