@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.
- package/bin/kgraph-launcher +15 -3
- package/lib/kgraph/scripts/build-bundle.sh +17 -4
- package/lib/site-packages/outcome/__init__.py +20 -0
- package/lib/site-packages/outcome/_impl.py +239 -0
- package/lib/site-packages/outcome/_util.py +33 -0
- package/lib/site-packages/outcome/_version.py +7 -0
- package/lib/site-packages/outcome/py.typed +0 -0
- package/lib/site-packages/outcome-1.3.0.post0.dist-info/INSTALLER +1 -0
- package/lib/site-packages/outcome-1.3.0.post0.dist-info/LICENSE +3 -0
- package/lib/site-packages/outcome-1.3.0.post0.dist-info/LICENSE.APACHE2 +202 -0
- package/lib/site-packages/outcome-1.3.0.post0.dist-info/LICENSE.MIT +20 -0
- package/lib/site-packages/outcome-1.3.0.post0.dist-info/METADATA +63 -0
- package/lib/site-packages/outcome-1.3.0.post0.dist-info/RECORD +13 -0
- package/lib/site-packages/outcome-1.3.0.post0.dist-info/WHEEL +6 -0
- package/lib/site-packages/outcome-1.3.0.post0.dist-info/top_level.txt +1 -0
- package/lib/site-packages/sniffio/__init__.py +17 -0
- package/lib/site-packages/sniffio/_impl.py +95 -0
- package/lib/site-packages/sniffio/_tests/__init__.py +0 -0
- package/lib/site-packages/sniffio/_tests/test_sniffio.py +84 -0
- package/lib/site-packages/sniffio/_version.py +3 -0
- package/lib/site-packages/sniffio/py.typed +0 -0
- package/lib/site-packages/sniffio-1.3.1.dist-info/INSTALLER +1 -0
- package/lib/site-packages/sniffio-1.3.1.dist-info/LICENSE +3 -0
- package/lib/site-packages/sniffio-1.3.1.dist-info/LICENSE.APACHE2 +202 -0
- package/lib/site-packages/sniffio-1.3.1.dist-info/LICENSE.MIT +20 -0
- package/lib/site-packages/sniffio-1.3.1.dist-info/METADATA +104 -0
- package/lib/site-packages/sniffio-1.3.1.dist-info/RECORD +14 -0
- package/lib/site-packages/sniffio-1.3.1.dist-info/WHEEL +5 -0
- package/lib/site-packages/sniffio-1.3.1.dist-info/top_level.txt +1 -0
- package/lib/site-packages/sortedcontainers/__init__.py +74 -0
- package/lib/site-packages/sortedcontainers/sorteddict.py +812 -0
- package/lib/site-packages/sortedcontainers/sortedlist.py +2646 -0
- package/lib/site-packages/sortedcontainers/sortedset.py +733 -0
- package/lib/site-packages/sortedcontainers-2.4.0.dist-info/INSTALLER +1 -0
- package/lib/site-packages/sortedcontainers-2.4.0.dist-info/LICENSE +13 -0
- package/lib/site-packages/sortedcontainers-2.4.0.dist-info/METADATA +264 -0
- package/lib/site-packages/sortedcontainers-2.4.0.dist-info/RECORD +10 -0
- package/lib/site-packages/sortedcontainers-2.4.0.dist-info/WHEEL +6 -0
- package/lib/site-packages/sortedcontainers-2.4.0.dist-info/top_level.txt +1 -0
- package/lib/site-packages/trio/__init__.py +133 -0
- package/lib/site-packages/trio/__main__.py +3 -0
- package/lib/site-packages/trio/_abc.py +714 -0
- package/lib/site-packages/trio/_channel.py +610 -0
- package/lib/site-packages/trio/_core/__init__.py +94 -0
- package/lib/site-packages/trio/_core/_asyncgens.py +243 -0
- package/lib/site-packages/trio/_core/_concat_tb.py +26 -0
- package/lib/site-packages/trio/_core/_entry_queue.py +223 -0
- package/lib/site-packages/trio/_core/_exceptions.py +169 -0
- package/lib/site-packages/trio/_core/_generated_instrumentation.py +50 -0
- package/lib/site-packages/trio/_core/_generated_io_epoll.py +98 -0
- package/lib/site-packages/trio/_core/_generated_io_kqueue.py +153 -0
- package/lib/site-packages/trio/_core/_generated_io_windows.py +204 -0
- package/lib/site-packages/trio/_core/_generated_run.py +269 -0
- package/lib/site-packages/trio/_core/_generated_windows_ffi.py +10 -0
- package/lib/site-packages/trio/_core/_instrumentation.py +117 -0
- package/lib/site-packages/trio/_core/_io_common.py +31 -0
- package/lib/site-packages/trio/_core/_io_epoll.py +385 -0
- package/lib/site-packages/trio/_core/_io_kqueue.py +292 -0
- package/lib/site-packages/trio/_core/_io_windows.py +1036 -0
- package/lib/site-packages/trio/_core/_ki.py +271 -0
- package/lib/site-packages/trio/_core/_local.py +104 -0
- package/lib/site-packages/trio/_core/_mock_clock.py +165 -0
- package/lib/site-packages/trio/_core/_parking_lot.py +317 -0
- package/lib/site-packages/trio/_core/_run.py +3148 -0
- package/lib/site-packages/trio/_core/_run_context.py +15 -0
- package/lib/site-packages/trio/_core/_tests/__init__.py +0 -0
- package/lib/site-packages/trio/_core/_tests/test_asyncgen.py +339 -0
- package/lib/site-packages/trio/_core/_tests/test_cancelled.py +222 -0
- package/lib/site-packages/trio/_core/_tests/test_exceptiongroup_gc.py +103 -0
- package/lib/site-packages/trio/_core/_tests/test_guest_mode.py +755 -0
- package/lib/site-packages/trio/_core/_tests/test_instrumentation.py +315 -0
- package/lib/site-packages/trio/_core/_tests/test_io.py +522 -0
- package/lib/site-packages/trio/_core/_tests/test_ki.py +703 -0
- package/lib/site-packages/trio/_core/_tests/test_local.py +118 -0
- package/lib/site-packages/trio/_core/_tests/test_mock_clock.py +193 -0
- package/lib/site-packages/trio/_core/_tests/test_parking_lot.py +389 -0
- package/lib/site-packages/trio/_core/_tests/test_run.py +3024 -0
- package/lib/site-packages/trio/_core/_tests/test_thread_cache.py +227 -0
- package/lib/site-packages/trio/_core/_tests/test_tutil.py +13 -0
- package/lib/site-packages/trio/_core/_tests/test_unbounded_queue.py +154 -0
- package/lib/site-packages/trio/_core/_tests/test_windows.py +305 -0
- package/lib/site-packages/trio/_core/_tests/tutil.py +117 -0
- package/lib/site-packages/trio/_core/_tests/type_tests/nursery_start.py +79 -0
- package/lib/site-packages/trio/_core/_tests/type_tests/run.py +51 -0
- package/lib/site-packages/trio/_core/_thread_cache.py +317 -0
- package/lib/site-packages/trio/_core/_traps.py +318 -0
- package/lib/site-packages/trio/_core/_unbounded_queue.py +163 -0
- package/lib/site-packages/trio/_core/_wakeup_socketpair.py +75 -0
- package/lib/site-packages/trio/_core/_windows_cffi.py +313 -0
- package/lib/site-packages/trio/_deprecate.py +171 -0
- package/lib/site-packages/trio/_dtls.py +1380 -0
- package/lib/site-packages/trio/_file_io.py +513 -0
- package/lib/site-packages/trio/_highlevel_generic.py +125 -0
- package/lib/site-packages/trio/_highlevel_open_tcp_listeners.py +251 -0
- package/lib/site-packages/trio/_highlevel_open_tcp_stream.py +397 -0
- package/lib/site-packages/trio/_highlevel_open_unix_stream.py +65 -0
- package/lib/site-packages/trio/_highlevel_serve_listeners.py +148 -0
- package/lib/site-packages/trio/_highlevel_socket.py +423 -0
- package/lib/site-packages/trio/_highlevel_ssl_helpers.py +180 -0
- package/lib/site-packages/trio/_path.py +289 -0
- package/lib/site-packages/trio/_repl.py +159 -0
- package/lib/site-packages/trio/_signals.py +185 -0
- package/lib/site-packages/trio/_socket.py +1326 -0
- package/lib/site-packages/trio/_ssl.py +964 -0
- package/lib/site-packages/trio/_subprocess.py +1178 -0
- package/lib/site-packages/trio/_subprocess_platform/__init__.py +123 -0
- package/lib/site-packages/trio/_subprocess_platform/kqueue.py +48 -0
- package/lib/site-packages/trio/_subprocess_platform/waitid.py +113 -0
- package/lib/site-packages/trio/_subprocess_platform/windows.py +11 -0
- package/lib/site-packages/trio/_sync.py +908 -0
- package/lib/site-packages/trio/_tests/__init__.py +0 -0
- package/lib/site-packages/trio/_tests/astrill-codesigning-cert.cer +0 -0
- package/lib/site-packages/trio/_tests/check_type_completeness.py +247 -0
- package/lib/site-packages/trio/_tests/module_with_deprecations.py +22 -0
- package/lib/site-packages/trio/_tests/pytest_plugin.py +54 -0
- package/lib/site-packages/trio/_tests/test_abc.py +72 -0
- package/lib/site-packages/trio/_tests/test_channel.py +750 -0
- package/lib/site-packages/trio/_tests/test_contextvars.py +56 -0
- package/lib/site-packages/trio/_tests/test_deprecate.py +277 -0
- package/lib/site-packages/trio/_tests/test_deprecate_strict_exception_groups_false.py +64 -0
- package/lib/site-packages/trio/_tests/test_dtls.py +950 -0
- package/lib/site-packages/trio/_tests/test_exports.py +626 -0
- package/lib/site-packages/trio/_tests/test_fakenet.py +317 -0
- package/lib/site-packages/trio/_tests/test_file_io.py +269 -0
- package/lib/site-packages/trio/_tests/test_highlevel_generic.py +98 -0
- package/lib/site-packages/trio/_tests/test_highlevel_open_tcp_listeners.py +419 -0
- package/lib/site-packages/trio/_tests/test_highlevel_open_tcp_stream.py +693 -0
- package/lib/site-packages/trio/_tests/test_highlevel_open_unix_stream.py +86 -0
- package/lib/site-packages/trio/_tests/test_highlevel_serve_listeners.py +186 -0
- package/lib/site-packages/trio/_tests/test_highlevel_socket.py +336 -0
- package/lib/site-packages/trio/_tests/test_highlevel_ssl_helpers.py +169 -0
- package/lib/site-packages/trio/_tests/test_path.py +279 -0
- package/lib/site-packages/trio/_tests/test_repl.py +428 -0
- package/lib/site-packages/trio/_tests/test_scheduler_determinism.py +47 -0
- package/lib/site-packages/trio/_tests/test_signals.py +186 -0
- package/lib/site-packages/trio/_tests/test_socket.py +1253 -0
- package/lib/site-packages/trio/_tests/test_ssl.py +1371 -0
- package/lib/site-packages/trio/_tests/test_subprocess.py +767 -0
- package/lib/site-packages/trio/_tests/test_sync.py +735 -0
- package/lib/site-packages/trio/_tests/test_testing.py +682 -0
- package/lib/site-packages/trio/_tests/test_testing_raisesgroup.py +1128 -0
- package/lib/site-packages/trio/_tests/test_threads.py +1173 -0
- package/lib/site-packages/trio/_tests/test_timeouts.py +281 -0
- package/lib/site-packages/trio/_tests/test_tracing.py +88 -0
- package/lib/site-packages/trio/_tests/test_trio.py +8 -0
- package/lib/site-packages/trio/_tests/test_unix_pipes.py +288 -0
- package/lib/site-packages/trio/_tests/test_util.py +349 -0
- package/lib/site-packages/trio/_tests/test_wait_for_object.py +225 -0
- package/lib/site-packages/trio/_tests/test_windows_pipes.py +112 -0
- package/lib/site-packages/trio/_tests/tools/__init__.py +0 -0
- package/lib/site-packages/trio/_tests/tools/test_gen_exports.py +179 -0
- package/lib/site-packages/trio/_tests/tools/test_mypy_annotate.py +140 -0
- package/lib/site-packages/trio/_tests/tools/test_sync_requirements.py +80 -0
- package/lib/site-packages/trio/_tests/type_tests/check_wraps.py +9 -0
- package/lib/site-packages/trio/_tests/type_tests/open_memory_channel.py +4 -0
- package/lib/site-packages/trio/_tests/type_tests/path.py +140 -0
- package/lib/site-packages/trio/_tests/type_tests/subprocesses.py +23 -0
- package/lib/site-packages/trio/_tests/type_tests/task_status.py +29 -0
- package/lib/site-packages/trio/_threads.py +610 -0
- package/lib/site-packages/trio/_timeouts.py +197 -0
- package/lib/site-packages/trio/_tools/__init__.py +0 -0
- package/lib/site-packages/trio/_tools/gen_exports.py +401 -0
- package/lib/site-packages/trio/_tools/mypy_annotate.py +126 -0
- package/lib/site-packages/trio/_tools/sync_requirements.py +98 -0
- package/lib/site-packages/trio/_tools/windows_ffi_build.py +220 -0
- package/lib/site-packages/trio/_unix_pipes.py +197 -0
- package/lib/site-packages/trio/_util.py +385 -0
- package/lib/site-packages/trio/_version.py +3 -0
- package/lib/site-packages/trio/_wait_for_object.py +67 -0
- package/lib/site-packages/trio/_windows_pipes.py +144 -0
- package/lib/site-packages/trio/abc.py +23 -0
- package/lib/site-packages/trio/from_thread.py +13 -0
- package/lib/site-packages/trio/lowlevel.py +95 -0
- package/lib/site-packages/trio/py.typed +0 -0
- package/lib/site-packages/trio/socket.py +602 -0
- package/lib/site-packages/trio/testing/__init__.py +58 -0
- package/lib/site-packages/trio/testing/_check_streams.py +570 -0
- package/lib/site-packages/trio/testing/_checkpoints.py +69 -0
- package/lib/site-packages/trio/testing/_fake_net.py +584 -0
- package/lib/site-packages/trio/testing/_memory_streams.py +633 -0
- package/lib/site-packages/trio/testing/_network.py +36 -0
- package/lib/site-packages/trio/testing/_raises_group.py +1015 -0
- package/lib/site-packages/trio/testing/_sequencer.py +87 -0
- package/lib/site-packages/trio/testing/_trio_test.py +50 -0
- package/lib/site-packages/trio/to_thread.py +4 -0
- package/lib/site-packages/trio-0.33.0.dist-info/INSTALLER +1 -0
- package/lib/site-packages/trio-0.33.0.dist-info/METADATA +186 -0
- package/lib/site-packages/trio-0.33.0.dist-info/RECORD +156 -0
- package/lib/site-packages/trio-0.33.0.dist-info/REQUESTED +0 -0
- package/lib/site-packages/trio-0.33.0.dist-info/WHEEL +5 -0
- package/lib/site-packages/trio-0.33.0.dist-info/entry_points.txt +2 -0
- package/lib/site-packages/trio-0.33.0.dist-info/licenses/LICENSE +3 -0
- package/lib/site-packages/trio-0.33.0.dist-info/licenses/LICENSE.APACHE2 +202 -0
- package/lib/site-packages/trio-0.33.0.dist-info/licenses/LICENSE.MIT +22 -0
- package/lib/site-packages/trio-0.33.0.dist-info/top_level.txt +1 -0
- 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)
|