@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,180 @@
1
+ from __future__ import annotations
2
+
3
+ import ssl
4
+ from typing import TYPE_CHECKING, NoReturn, TypeVar
5
+
6
+ import trio
7
+
8
+ from ._highlevel_open_tcp_stream import DEFAULT_DELAY
9
+
10
+ T = TypeVar("T")
11
+
12
+ if TYPE_CHECKING:
13
+ from collections.abc import Awaitable, Callable
14
+
15
+ from ._highlevel_socket import SocketStream
16
+
17
+
18
+ # It might have been nice to take a ssl_protocols= argument here to set up
19
+ # NPN/ALPN, but to do this we have to mutate the context object, which is OK
20
+ # if it's one we created, but not OK if it's one that was passed in... and
21
+ # the one major protocol using NPN/ALPN is HTTP/2, which mandates that you use
22
+ # a specially configured SSLContext anyway! I also thought maybe we could copy
23
+ # the given SSLContext and then mutate the copy, but it's no good as SSLContext
24
+ # objects can't be copied: https://bugs.python.org/issue33023.
25
+ # So... let's punt on that for now. Hopefully we'll be getting a new Python
26
+ # TLS API soon and can revisit this then.
27
+ async def open_ssl_over_tcp_stream(
28
+ host: str | bytes,
29
+ port: int,
30
+ *,
31
+ https_compatible: bool = False,
32
+ ssl_context: ssl.SSLContext | None = None,
33
+ happy_eyeballs_delay: float | None = DEFAULT_DELAY,
34
+ ) -> trio.SSLStream[SocketStream]:
35
+ """Make a TLS-encrypted Connection to the given host and port over TCP.
36
+
37
+ This is a convenience wrapper that calls :func:`open_tcp_stream` and
38
+ wraps the result in an :class:`~trio.SSLStream`.
39
+
40
+ This function does not perform the TLS handshake; you can do it
41
+ manually by calling :meth:`~trio.SSLStream.do_handshake`, or else
42
+ it will be performed automatically the first time you send or receive
43
+ data.
44
+
45
+ Args:
46
+ host (bytes or str): The host to connect to. We require the server
47
+ to have a TLS certificate valid for this hostname.
48
+ port (int): The port to connect to.
49
+ https_compatible (bool): Set this to True if you're connecting to a web
50
+ server. See :class:`~trio.SSLStream` for details. Default:
51
+ False.
52
+ ssl_context (:class:`~ssl.SSLContext` or None): The SSL context to
53
+ use. If None (the default), :func:`ssl.create_default_context`
54
+ will be called to create a context.
55
+ happy_eyeballs_delay (float): See :func:`open_tcp_stream`.
56
+
57
+ Returns:
58
+ trio.SSLStream: the encrypted connection to the server.
59
+
60
+ """
61
+ tcp_stream = await trio.open_tcp_stream(
62
+ host,
63
+ port,
64
+ happy_eyeballs_delay=happy_eyeballs_delay,
65
+ )
66
+ if ssl_context is None:
67
+ ssl_context = ssl.create_default_context()
68
+
69
+ if hasattr(ssl, "OP_IGNORE_UNEXPECTED_EOF"):
70
+ ssl_context.options &= ~ssl.OP_IGNORE_UNEXPECTED_EOF
71
+
72
+ return trio.SSLStream(
73
+ tcp_stream,
74
+ ssl_context,
75
+ server_hostname=host,
76
+ https_compatible=https_compatible,
77
+ )
78
+
79
+
80
+ async def open_ssl_over_tcp_listeners(
81
+ port: int,
82
+ ssl_context: ssl.SSLContext,
83
+ *,
84
+ host: str | bytes | None = None,
85
+ https_compatible: bool = False,
86
+ backlog: int | None = None,
87
+ ) -> list[trio.SSLListener[SocketStream]]:
88
+ """Start listening for SSL/TLS-encrypted TCP connections to the given port.
89
+
90
+ Args:
91
+ port (int): The port to listen on. See :func:`open_tcp_listeners`.
92
+ ssl_context (~ssl.SSLContext): The SSL context to use for all incoming
93
+ connections.
94
+ host (str, bytes, or None): The address to bind to; use ``None`` to bind
95
+ to the wildcard address. See :func:`open_tcp_listeners`.
96
+ https_compatible (bool): See :class:`~trio.SSLStream` for details.
97
+ backlog (int or None): See :func:`open_tcp_listeners` for details.
98
+
99
+ """
100
+ tcp_listeners = await trio.open_tcp_listeners(port, host=host, backlog=backlog)
101
+ ssl_listeners = [
102
+ trio.SSLListener(tcp_listener, ssl_context, https_compatible=https_compatible)
103
+ for tcp_listener in tcp_listeners
104
+ ]
105
+ return ssl_listeners
106
+
107
+
108
+ async def serve_ssl_over_tcp(
109
+ handler: Callable[[trio.SSLStream[SocketStream]], Awaitable[object]],
110
+ port: int,
111
+ ssl_context: ssl.SSLContext,
112
+ *,
113
+ host: str | bytes | None = None,
114
+ https_compatible: bool = False,
115
+ backlog: int | None = None,
116
+ handler_nursery: trio.Nursery | None = None,
117
+ task_status: trio.TaskStatus[
118
+ list[trio.SSLListener[SocketStream]]
119
+ ] = trio.TASK_STATUS_IGNORED,
120
+ ) -> NoReturn:
121
+ """Listen for incoming TCP connections, and for each one start a task
122
+ running ``handler(stream)``.
123
+
124
+ This is a thin convenience wrapper around
125
+ :func:`open_ssl_over_tcp_listeners` and :func:`serve_listeners` – see them
126
+ for full details.
127
+
128
+ .. warning::
129
+
130
+ If ``handler`` raises an exception, then this function doesn't do
131
+ anything special to catch it – so by default the exception will
132
+ propagate out and crash your server. If you don't want this, then catch
133
+ exceptions inside your ``handler``, or use a ``handler_nursery`` object
134
+ that responds to exceptions in some other way.
135
+
136
+ When used with ``nursery.start`` you get back the newly opened listeners.
137
+ See the documentation for :func:`serve_tcp` for an example where this is
138
+ useful.
139
+
140
+ Args:
141
+ handler: The handler to start for each incoming connection. Passed to
142
+ :func:`serve_listeners`.
143
+
144
+ port (int): The port to listen on. Use 0 to let the kernel pick
145
+ an open port. Ultimately passed to :func:`open_tcp_listeners`.
146
+
147
+ ssl_context (~ssl.SSLContext): The SSL context to use for all incoming
148
+ connections. Passed to :func:`open_ssl_over_tcp_listeners`.
149
+
150
+ host (str, bytes, or None): The address to bind to; use ``None`` to bind
151
+ to the wildcard address. Ultimately passed to
152
+ :func:`open_tcp_listeners`.
153
+
154
+ https_compatible (bool): Set this to True if you want to use
155
+ "HTTPS-style" TLS. See :class:`~trio.SSLStream` for details.
156
+
157
+ backlog (int or None): See :class:`~trio.SSLStream` for details.
158
+
159
+ handler_nursery: The nursery to start handlers in, or None to use an
160
+ internal nursery. Passed to :func:`serve_listeners`.
161
+
162
+ task_status: This function can be used with ``nursery.start``.
163
+
164
+ Returns:
165
+ This function only returns when cancelled.
166
+
167
+ """
168
+ listeners = await trio.open_ssl_over_tcp_listeners(
169
+ port,
170
+ ssl_context,
171
+ host=host,
172
+ https_compatible=https_compatible,
173
+ backlog=backlog,
174
+ )
175
+ await trio.serve_listeners(
176
+ handler,
177
+ listeners,
178
+ handler_nursery=handler_nursery,
179
+ task_status=task_status,
180
+ )
@@ -0,0 +1,289 @@
1
+ from __future__ import annotations
2
+
3
+ import os
4
+ import pathlib
5
+ import sys
6
+ from functools import partial, update_wrapper
7
+ from inspect import cleandoc
8
+ from typing import (
9
+ IO,
10
+ TYPE_CHECKING,
11
+ Any,
12
+ BinaryIO,
13
+ ClassVar,
14
+ Concatenate,
15
+ Literal,
16
+ TypeVar,
17
+ overload,
18
+ )
19
+
20
+ from trio._file_io import AsyncIOWrapper, wrap_file
21
+ from trio._util import final
22
+ from trio.to_thread import run_sync
23
+
24
+ if TYPE_CHECKING:
25
+ from collections.abc import Awaitable, Callable, Iterable
26
+ from io import BufferedRandom, BufferedReader, BufferedWriter, FileIO, TextIOWrapper
27
+
28
+ from _typeshed import (
29
+ OpenBinaryMode,
30
+ OpenBinaryModeReading,
31
+ OpenBinaryModeUpdating,
32
+ OpenBinaryModeWriting,
33
+ OpenTextMode,
34
+ )
35
+ from typing_extensions import ParamSpec, Self
36
+
37
+ P = ParamSpec("P")
38
+
39
+ PathT = TypeVar("PathT", bound="Path")
40
+ T = TypeVar("T")
41
+
42
+
43
+ def _wraps_async( # type: ignore[explicit-any]
44
+ wrapped: Callable[..., object],
45
+ ) -> Callable[[Callable[P, T]], Callable[P, Awaitable[T]]]:
46
+ def decorator(fn: Callable[P, T]) -> Callable[P, Awaitable[T]]:
47
+ async def wrapper(*args: P.args, **kwargs: P.kwargs) -> T:
48
+ return await run_sync(partial(fn, *args, **kwargs))
49
+
50
+ update_wrapper(wrapper, wrapped)
51
+ if wrapped.__doc__:
52
+ module = wrapped.__module__
53
+ # these are exported specially from CPython's intersphinx inventory
54
+ module = module.replace("pathlib._local", "pathlib")
55
+ module = module.replace("pathlib._abc", "pathlib")
56
+
57
+ name = wrapped.__qualname__
58
+ name = name.replace(
59
+ "PathBase", "Path"
60
+ ) # I'm not sure why this is necessary
61
+
62
+ wrapper.__doc__ = (
63
+ f"Like :meth:`~{module}.{name}`, but async.\n"
64
+ f"\n"
65
+ f"{cleandoc(wrapped.__doc__)}\n"
66
+ )
67
+ return wrapper
68
+
69
+ return decorator
70
+
71
+
72
+ def _wrap_method(
73
+ fn: Callable[Concatenate[pathlib.Path, P], T],
74
+ ) -> Callable[Concatenate[Path, P], Awaitable[T]]:
75
+ @_wraps_async(fn)
76
+ def wrapper(self: Path, /, *args: P.args, **kwargs: P.kwargs) -> T:
77
+ return fn(self._wrapped_cls(self), *args, **kwargs)
78
+
79
+ return wrapper
80
+
81
+
82
+ def _wrap_method_path(
83
+ fn: Callable[Concatenate[pathlib.Path, P], pathlib.Path],
84
+ ) -> Callable[Concatenate[PathT, P], Awaitable[PathT]]:
85
+ @_wraps_async(fn)
86
+ def wrapper(self: PathT, /, *args: P.args, **kwargs: P.kwargs) -> PathT:
87
+ return self.__class__(fn(self._wrapped_cls(self), *args, **kwargs))
88
+
89
+ return wrapper
90
+
91
+
92
+ def _wrap_method_path_iterable(
93
+ fn: Callable[Concatenate[pathlib.Path, P], Iterable[pathlib.Path]],
94
+ ) -> Callable[Concatenate[PathT, P], Awaitable[Iterable[PathT]]]:
95
+ @_wraps_async(fn)
96
+ def wrapper(self: PathT, /, *args: P.args, **kwargs: P.kwargs) -> Iterable[PathT]:
97
+ return map(self.__class__, [*fn(self._wrapped_cls(self), *args, **kwargs)])
98
+
99
+ if wrapper.__doc__:
100
+ wrapper.__doc__ += (
101
+ f"\n"
102
+ f"This is an async method that returns a synchronous iterator, so you\n"
103
+ f"use it like:\n"
104
+ f"\n"
105
+ f".. code:: python\n"
106
+ f"\n"
107
+ f" for subpath in await mypath.{fn.__name__}():\n"
108
+ f" ...\n"
109
+ f"\n"
110
+ f".. note::\n"
111
+ f"\n"
112
+ f" The iterator is loaded into memory immediately during the initial\n"
113
+ f" call (see `issue #501\n"
114
+ f" <https://github.com/python-trio/trio/issues/501>`__ for discussion).\n"
115
+ )
116
+ return wrapper
117
+
118
+
119
+ class Path(pathlib.PurePath):
120
+ """An async :class:`pathlib.Path` that executes blocking methods in :meth:`trio.to_thread.run_sync`.
121
+
122
+ Instantiating :class:`Path` returns a concrete platform-specific subclass, one of :class:`PosixPath` or
123
+ :class:`WindowsPath`.
124
+ """
125
+
126
+ __slots__ = ()
127
+
128
+ _wrapped_cls: ClassVar[type[pathlib.Path]]
129
+
130
+ def __new__(cls, *args: str | os.PathLike[str]) -> Self:
131
+ if cls is Path:
132
+ cls = WindowsPath if os.name == "nt" else PosixPath # type: ignore[assignment]
133
+ return super().__new__(cls, *args)
134
+
135
+ @classmethod
136
+ @_wraps_async(pathlib.Path.cwd)
137
+ def cwd(cls) -> Self:
138
+ return cls(pathlib.Path.cwd())
139
+
140
+ @classmethod
141
+ @_wraps_async(pathlib.Path.home)
142
+ def home(cls) -> Self:
143
+ return cls(pathlib.Path.home())
144
+
145
+ @overload
146
+ async def open(
147
+ self,
148
+ mode: OpenTextMode = "r",
149
+ buffering: int = -1,
150
+ encoding: str | None = None,
151
+ errors: str | None = None,
152
+ newline: str | None = None,
153
+ ) -> AsyncIOWrapper[TextIOWrapper]: ...
154
+
155
+ @overload
156
+ async def open(
157
+ self,
158
+ mode: OpenBinaryMode,
159
+ buffering: Literal[0],
160
+ encoding: None = None,
161
+ errors: None = None,
162
+ newline: None = None,
163
+ ) -> AsyncIOWrapper[FileIO]: ...
164
+
165
+ @overload
166
+ async def open(
167
+ self,
168
+ mode: OpenBinaryModeUpdating,
169
+ buffering: Literal[-1, 1] = -1,
170
+ encoding: None = None,
171
+ errors: None = None,
172
+ newline: None = None,
173
+ ) -> AsyncIOWrapper[BufferedRandom]: ...
174
+
175
+ @overload
176
+ async def open(
177
+ self,
178
+ mode: OpenBinaryModeWriting,
179
+ buffering: Literal[-1, 1] = -1,
180
+ encoding: None = None,
181
+ errors: None = None,
182
+ newline: None = None,
183
+ ) -> AsyncIOWrapper[BufferedWriter]: ...
184
+
185
+ @overload
186
+ async def open(
187
+ self,
188
+ mode: OpenBinaryModeReading,
189
+ buffering: Literal[-1, 1] = -1,
190
+ encoding: None = None,
191
+ errors: None = None,
192
+ newline: None = None,
193
+ ) -> AsyncIOWrapper[BufferedReader]: ...
194
+
195
+ @overload
196
+ async def open(
197
+ self,
198
+ mode: OpenBinaryMode,
199
+ buffering: int = -1,
200
+ encoding: None = None,
201
+ errors: None = None,
202
+ newline: None = None,
203
+ ) -> AsyncIOWrapper[BinaryIO]: ...
204
+
205
+ @overload
206
+ async def open( # type: ignore[explicit-any] # Any usage matches builtins.open().
207
+ self,
208
+ mode: str,
209
+ buffering: int = -1,
210
+ encoding: str | None = None,
211
+ errors: str | None = None,
212
+ newline: str | None = None,
213
+ ) -> AsyncIOWrapper[IO[Any]]: ...
214
+
215
+ @_wraps_async(pathlib.Path.open)
216
+ def open(self, *args: Any, **kwargs: Any) -> AsyncIOWrapper[IO[Any]]: # type: ignore[misc, explicit-any] # Overload return mismatch.
217
+ return wrap_file(self._wrapped_cls(self).open(*args, **kwargs))
218
+
219
+ def __repr__(self) -> str:
220
+ return f"trio.Path({str(self)!r})"
221
+
222
+ stat = _wrap_method(pathlib.Path.stat)
223
+ chmod = _wrap_method(pathlib.Path.chmod)
224
+ exists = _wrap_method(pathlib.Path.exists)
225
+ glob = _wrap_method_path_iterable(pathlib.Path.glob)
226
+ rglob = _wrap_method_path_iterable(pathlib.Path.rglob)
227
+ is_dir = _wrap_method(pathlib.Path.is_dir)
228
+ is_file = _wrap_method(pathlib.Path.is_file)
229
+ is_symlink = _wrap_method(pathlib.Path.is_symlink)
230
+ is_socket = _wrap_method(pathlib.Path.is_socket)
231
+ is_fifo = _wrap_method(pathlib.Path.is_fifo)
232
+ is_block_device = _wrap_method(pathlib.Path.is_block_device)
233
+ is_char_device = _wrap_method(pathlib.Path.is_char_device)
234
+ if sys.version_info >= (3, 12):
235
+ is_junction = _wrap_method(pathlib.Path.is_junction)
236
+ iterdir = _wrap_method_path_iterable(pathlib.Path.iterdir)
237
+ lchmod = _wrap_method(pathlib.Path.lchmod)
238
+ lstat = _wrap_method(pathlib.Path.lstat)
239
+ mkdir = _wrap_method(pathlib.Path.mkdir)
240
+ if sys.platform != "win32":
241
+ owner = _wrap_method(pathlib.Path.owner)
242
+ group = _wrap_method(pathlib.Path.group)
243
+ if sys.platform != "win32" or sys.version_info >= (3, 12):
244
+ is_mount = _wrap_method(pathlib.Path.is_mount)
245
+ readlink = _wrap_method_path(pathlib.Path.readlink)
246
+ rename = _wrap_method_path(pathlib.Path.rename)
247
+ replace = _wrap_method_path(pathlib.Path.replace)
248
+ resolve = _wrap_method_path(pathlib.Path.resolve)
249
+ rmdir = _wrap_method(pathlib.Path.rmdir)
250
+ symlink_to = _wrap_method(pathlib.Path.symlink_to)
251
+ hardlink_to = _wrap_method(pathlib.Path.hardlink_to)
252
+ touch = _wrap_method(pathlib.Path.touch)
253
+ unlink = _wrap_method(pathlib.Path.unlink)
254
+ absolute = _wrap_method_path(pathlib.Path.absolute)
255
+ expanduser = _wrap_method_path(pathlib.Path.expanduser)
256
+ read_bytes = _wrap_method(pathlib.Path.read_bytes)
257
+ read_text = _wrap_method(pathlib.Path.read_text)
258
+ samefile = _wrap_method(pathlib.Path.samefile)
259
+ write_bytes = _wrap_method(pathlib.Path.write_bytes)
260
+ write_text = _wrap_method(pathlib.Path.write_text)
261
+ if sys.version_info < (3, 12):
262
+ link_to = _wrap_method(pathlib.Path.link_to)
263
+ if sys.version_info >= (3, 13):
264
+ full_match = _wrap_method(pathlib.Path.full_match)
265
+
266
+ def as_uri(self) -> str:
267
+ return pathlib.Path.as_uri(self)
268
+
269
+
270
+ if Path.relative_to.__doc__: # pragma: no branch
271
+ Path.relative_to.__doc__ = Path.relative_to.__doc__.replace(" `..` ", " ``..`` ")
272
+
273
+
274
+ @final
275
+ class PosixPath(Path, pathlib.PurePosixPath):
276
+ """An async :class:`pathlib.PosixPath` that executes blocking methods in :meth:`trio.to_thread.run_sync`."""
277
+
278
+ __slots__ = ()
279
+
280
+ _wrapped_cls: ClassVar[type[pathlib.Path]] = pathlib.PosixPath
281
+
282
+
283
+ @final
284
+ class WindowsPath(Path, pathlib.PureWindowsPath):
285
+ """An async :class:`pathlib.WindowsPath` that executes blocking methods in :meth:`trio.to_thread.run_sync`."""
286
+
287
+ __slots__ = ()
288
+
289
+ _wrapped_cls: ClassVar[type[pathlib.Path]] = pathlib.WindowsPath
@@ -0,0 +1,159 @@
1
+ from __future__ import annotations
2
+
3
+ import ast
4
+ import contextlib
5
+ import inspect
6
+ import sys
7
+ import warnings
8
+ from code import InteractiveConsole
9
+ from types import CodeType, FrameType, FunctionType
10
+ from typing import TYPE_CHECKING
11
+
12
+ import outcome
13
+
14
+ import trio
15
+ import trio.lowlevel
16
+ from trio._util import final
17
+
18
+ if TYPE_CHECKING:
19
+ from collections.abc import Callable
20
+
21
+
22
+ class SuppressDecorator(contextlib.ContextDecorator, contextlib.suppress):
23
+ pass
24
+
25
+
26
+ @SuppressDecorator(KeyboardInterrupt)
27
+ @trio.lowlevel.disable_ki_protection
28
+ def terminal_newline() -> None: # TODO: test this line
29
+ import fcntl
30
+ import termios
31
+
32
+ # Fake up a newline char as if user had typed it at the terminal
33
+ try:
34
+ fcntl.ioctl(sys.stdin, termios.TIOCSTI, b"\n") # type: ignore[attr-defined, unused-ignore]
35
+ except OSError as e:
36
+ print(f"\nPress enter! Newline injection failed: {e}", end="", flush=True)
37
+
38
+
39
+ @final
40
+ class TrioInteractiveConsole(InteractiveConsole):
41
+ def __init__(self, repl_locals: dict[str, object] | None = None) -> None:
42
+ super().__init__(locals=repl_locals)
43
+ self.token: trio.lowlevel.TrioToken | None = None
44
+ self.compile.compiler.flags |= ast.PyCF_ALLOW_TOP_LEVEL_AWAIT
45
+ self.interrupted = False
46
+
47
+ def runcode(self, code: CodeType) -> None:
48
+ func = FunctionType(code, self.locals)
49
+ if inspect.iscoroutinefunction(func):
50
+ result = trio.from_thread.run(outcome.acapture, func)
51
+ else:
52
+ result = trio.from_thread.run_sync(outcome.capture, func)
53
+ if isinstance(result, outcome.Error):
54
+ # If it is SystemExit, quit the repl. Otherwise, print the traceback.
55
+ # If there is a SystemExit inside a BaseExceptionGroup, it probably isn't
56
+ # the user trying to quit the repl, but rather an error in the code. So, we
57
+ # don't try to inspect groups for SystemExit. Instead, we just print and
58
+ # return to the REPL.
59
+ if isinstance(result.error, SystemExit):
60
+ raise result.error
61
+ else:
62
+ # Inline our own version of self.showtraceback that can use
63
+ # outcome.Error.error directly to print clean tracebacks.
64
+ # This also means overriding self.showtraceback does nothing.
65
+ sys.last_type, sys.last_value = type(result.error), result.error
66
+ sys.last_traceback = result.error.__traceback__
67
+ # see https://docs.python.org/3/library/sys.html#sys.last_exc
68
+ if sys.version_info >= (3, 12):
69
+ sys.last_exc = result.error
70
+
71
+ # We always use sys.excepthook, unlike other implementations.
72
+ # This means that overriding self.write also does nothing to tbs.
73
+ sys.excepthook(sys.last_type, sys.last_value, sys.last_traceback)
74
+ # clear any residual KI
75
+ trio.from_thread.run(trio.lowlevel.checkpoint_if_cancelled)
76
+ # trio.from_thread.check_cancelled() has too long of a memory
77
+
78
+ if sys.platform == "win32": # TODO: test this line
79
+
80
+ def raw_input(self, prompt: str = "") -> str:
81
+ try:
82
+ return input(prompt)
83
+ except EOFError:
84
+ # check if trio has a pending KI
85
+ trio.from_thread.run(trio.lowlevel.checkpoint_if_cancelled)
86
+ raise
87
+
88
+ else:
89
+
90
+ def raw_input(self, prompt: str = "") -> str:
91
+ from signal import SIGINT, signal
92
+
93
+ assert not self.interrupted
94
+
95
+ def install_handler() -> (
96
+ Callable[[int, FrameType | None], None] | int | None
97
+ ):
98
+ def handler(
99
+ sig: int, frame: FrameType | None
100
+ ) -> None: # TODO: test this line
101
+ self.interrupted = True
102
+ token.run_sync_soon(terminal_newline, idempotent=True)
103
+
104
+ token = trio.lowlevel.current_trio_token()
105
+
106
+ return signal(SIGINT, handler)
107
+
108
+ prev_handler = trio.from_thread.run_sync(install_handler)
109
+ try:
110
+ return input(prompt)
111
+ finally:
112
+ trio.from_thread.run_sync(signal, SIGINT, prev_handler)
113
+ if self.interrupted: # TODO: test this line
114
+ raise KeyboardInterrupt
115
+
116
+ def write(self, output: str) -> None:
117
+ if self.interrupted: # TODO: test this line
118
+ assert output == "\nKeyboardInterrupt\n"
119
+ sys.stderr.write(output[1:])
120
+ self.interrupted = False
121
+ else:
122
+ sys.stderr.write(output)
123
+
124
+
125
+ async def run_repl(console: TrioInteractiveConsole) -> None:
126
+ banner = (
127
+ f"trio REPL {sys.version} on {sys.platform}\n"
128
+ f'Use "await" directly instead of "trio.run()".\n'
129
+ f'Type "help", "copyright", "credits" or "license" '
130
+ f"for more information.\n"
131
+ f'{getattr(sys, "ps1", ">>> ")}import trio'
132
+ )
133
+ try:
134
+ await trio.to_thread.run_sync(console.interact, banner)
135
+ finally:
136
+ warnings.filterwarnings(
137
+ "ignore",
138
+ message=r"^coroutine .* was never awaited$",
139
+ category=RuntimeWarning,
140
+ )
141
+
142
+
143
+ def main(original_locals: dict[str, object]) -> None:
144
+ with contextlib.suppress(ImportError):
145
+ import readline # noqa: F401
146
+
147
+ repl_locals: dict[str, object] = {"trio": trio}
148
+ for key in {
149
+ "__name__",
150
+ "__package__",
151
+ "__loader__",
152
+ "__spec__",
153
+ "__builtins__",
154
+ "__file__",
155
+ }:
156
+ repl_locals[key] = original_locals[key]
157
+
158
+ console = TrioInteractiveConsole(repl_locals)
159
+ trio.run(run_repl, console)