@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,169 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from functools import partial
|
|
4
|
+
from typing import TYPE_CHECKING, NoReturn, cast
|
|
5
|
+
|
|
6
|
+
import attrs
|
|
7
|
+
import pytest
|
|
8
|
+
|
|
9
|
+
import trio
|
|
10
|
+
from trio.socket import AF_INET, IPPROTO_TCP, SOCK_STREAM
|
|
11
|
+
|
|
12
|
+
from .._highlevel_ssl_helpers import (
|
|
13
|
+
open_ssl_over_tcp_listeners,
|
|
14
|
+
open_ssl_over_tcp_stream,
|
|
15
|
+
serve_ssl_over_tcp,
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
# using noqa because linters don't understand how pytest fixtures work.
|
|
19
|
+
from .test_ssl import SERVER_CTX, client_ctx # noqa: F401
|
|
20
|
+
|
|
21
|
+
if TYPE_CHECKING:
|
|
22
|
+
from socket import AddressFamily, SocketKind
|
|
23
|
+
from ssl import SSLContext
|
|
24
|
+
|
|
25
|
+
from trio.abc import Stream
|
|
26
|
+
|
|
27
|
+
from .._highlevel_socket import SocketListener
|
|
28
|
+
from .._ssl import SSLListener
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
async def echo_handler(stream: Stream) -> None:
|
|
32
|
+
async with stream:
|
|
33
|
+
try:
|
|
34
|
+
while True:
|
|
35
|
+
data = await stream.receive_some(10000)
|
|
36
|
+
if not data:
|
|
37
|
+
break
|
|
38
|
+
await stream.send_all(data)
|
|
39
|
+
except trio.BrokenResourceError:
|
|
40
|
+
pass
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
# Resolver that always returns the given sockaddr, no matter what host/port
|
|
44
|
+
# you ask for.
|
|
45
|
+
@attrs.define(slots=False)
|
|
46
|
+
class FakeHostnameResolver(trio.abc.HostnameResolver):
|
|
47
|
+
sockaddr: tuple[str, int] | tuple[str, int, int, int] | tuple[int, bytes]
|
|
48
|
+
|
|
49
|
+
async def getaddrinfo(
|
|
50
|
+
self,
|
|
51
|
+
host: bytes | None,
|
|
52
|
+
port: bytes | str | int | None,
|
|
53
|
+
family: int = 0,
|
|
54
|
+
type: int = 0,
|
|
55
|
+
proto: int = 0,
|
|
56
|
+
flags: int = 0,
|
|
57
|
+
) -> list[
|
|
58
|
+
tuple[
|
|
59
|
+
AddressFamily,
|
|
60
|
+
SocketKind,
|
|
61
|
+
int,
|
|
62
|
+
str,
|
|
63
|
+
tuple[str, int] | tuple[str, int, int, int] | tuple[int, bytes],
|
|
64
|
+
]
|
|
65
|
+
]:
|
|
66
|
+
return [(AF_INET, SOCK_STREAM, IPPROTO_TCP, "", self.sockaddr)]
|
|
67
|
+
|
|
68
|
+
async def getnameinfo(
|
|
69
|
+
self,
|
|
70
|
+
sockaddr: tuple[str, int] | tuple[str, int, int, int],
|
|
71
|
+
flags: int,
|
|
72
|
+
) -> NoReturn: # pragma: no cover
|
|
73
|
+
raise NotImplementedError
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
# This uses serve_ssl_over_tcp, which uses open_ssl_over_tcp_listeners...
|
|
77
|
+
# using noqa because linters don't understand how pytest fixtures work.
|
|
78
|
+
async def test_open_ssl_over_tcp_stream_and_everything_else(
|
|
79
|
+
client_ctx: SSLContext, # noqa: F811 # linters doesn't understand fixture
|
|
80
|
+
) -> None:
|
|
81
|
+
async with trio.open_nursery() as nursery:
|
|
82
|
+
# TODO: this function wraps an SSLListener around a SocketListener, this is illegal
|
|
83
|
+
# according to current type hints, and probably for good reason. But there should
|
|
84
|
+
# maybe be a different wrapper class/function that could be used instead?
|
|
85
|
+
value = await nursery.start(
|
|
86
|
+
partial(
|
|
87
|
+
serve_ssl_over_tcp,
|
|
88
|
+
echo_handler,
|
|
89
|
+
0,
|
|
90
|
+
SERVER_CTX,
|
|
91
|
+
host="127.0.0.1",
|
|
92
|
+
),
|
|
93
|
+
)
|
|
94
|
+
assert isinstance(value, list)
|
|
95
|
+
res = cast("list[SSLListener[SocketListener]]", value) # type: ignore[type-var]
|
|
96
|
+
(listener,) = res
|
|
97
|
+
async with listener:
|
|
98
|
+
# listener.transport_listener is of type Listener[Stream]
|
|
99
|
+
tp_listener: SocketListener = listener.transport_listener # type: ignore[assignment]
|
|
100
|
+
|
|
101
|
+
sockaddr = tp_listener.socket.getsockname()
|
|
102
|
+
hostname_resolver = FakeHostnameResolver(sockaddr)
|
|
103
|
+
trio.socket.set_custom_hostname_resolver(hostname_resolver)
|
|
104
|
+
|
|
105
|
+
# We don't have the right trust set up
|
|
106
|
+
# (checks that ssl_context=None is doing some validation)
|
|
107
|
+
stream = await open_ssl_over_tcp_stream("trio-test-1.example.org", 80)
|
|
108
|
+
async with stream:
|
|
109
|
+
with pytest.raises(trio.BrokenResourceError):
|
|
110
|
+
await stream.do_handshake()
|
|
111
|
+
|
|
112
|
+
# We have the trust but not the hostname
|
|
113
|
+
# (checks custom ssl_context + hostname checking)
|
|
114
|
+
stream = await open_ssl_over_tcp_stream(
|
|
115
|
+
"xyzzy.example.org",
|
|
116
|
+
80,
|
|
117
|
+
ssl_context=client_ctx,
|
|
118
|
+
)
|
|
119
|
+
async with stream:
|
|
120
|
+
with pytest.raises(trio.BrokenResourceError):
|
|
121
|
+
await stream.do_handshake()
|
|
122
|
+
|
|
123
|
+
# This one should work!
|
|
124
|
+
stream = await open_ssl_over_tcp_stream(
|
|
125
|
+
"trio-test-1.example.org",
|
|
126
|
+
80,
|
|
127
|
+
ssl_context=client_ctx,
|
|
128
|
+
)
|
|
129
|
+
async with stream:
|
|
130
|
+
assert isinstance(stream, trio.SSLStream)
|
|
131
|
+
assert stream.server_hostname == "trio-test-1.example.org"
|
|
132
|
+
await stream.send_all(b"x")
|
|
133
|
+
assert await stream.receive_some(1) == b"x"
|
|
134
|
+
|
|
135
|
+
# Check https_compatible settings are being passed through
|
|
136
|
+
assert not stream._https_compatible
|
|
137
|
+
stream = await open_ssl_over_tcp_stream(
|
|
138
|
+
"trio-test-1.example.org",
|
|
139
|
+
80,
|
|
140
|
+
ssl_context=client_ctx,
|
|
141
|
+
https_compatible=True,
|
|
142
|
+
# also, smoke test happy_eyeballs_delay
|
|
143
|
+
happy_eyeballs_delay=1,
|
|
144
|
+
)
|
|
145
|
+
async with stream:
|
|
146
|
+
assert stream._https_compatible
|
|
147
|
+
|
|
148
|
+
# Stop the echo server
|
|
149
|
+
nursery.cancel_scope.cancel()
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
async def test_open_ssl_over_tcp_listeners() -> None:
|
|
153
|
+
(listener,) = await open_ssl_over_tcp_listeners(0, SERVER_CTX, host="127.0.0.1")
|
|
154
|
+
async with listener:
|
|
155
|
+
assert isinstance(listener, trio.SSLListener)
|
|
156
|
+
tl = listener.transport_listener
|
|
157
|
+
assert isinstance(tl, trio.SocketListener)
|
|
158
|
+
assert tl.socket.getsockname()[0] == "127.0.0.1"
|
|
159
|
+
|
|
160
|
+
assert not listener._https_compatible
|
|
161
|
+
|
|
162
|
+
(listener,) = await open_ssl_over_tcp_listeners(
|
|
163
|
+
0,
|
|
164
|
+
SERVER_CTX,
|
|
165
|
+
host="127.0.0.1",
|
|
166
|
+
https_compatible=True,
|
|
167
|
+
)
|
|
168
|
+
async with listener:
|
|
169
|
+
assert listener._https_compatible
|
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
import pathlib
|
|
5
|
+
from typing import TYPE_CHECKING
|
|
6
|
+
|
|
7
|
+
import pytest
|
|
8
|
+
|
|
9
|
+
import trio
|
|
10
|
+
from trio._file_io import AsyncIOWrapper
|
|
11
|
+
|
|
12
|
+
if TYPE_CHECKING:
|
|
13
|
+
from collections.abc import Awaitable, Callable
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@pytest.fixture
|
|
17
|
+
def path(tmp_path: pathlib.Path) -> trio.Path:
|
|
18
|
+
return trio.Path(tmp_path / "test")
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def method_pair(
|
|
22
|
+
path: str,
|
|
23
|
+
method_name: str,
|
|
24
|
+
) -> tuple[Callable[[], object], Callable[[], Awaitable[object]]]:
|
|
25
|
+
sync_path = pathlib.Path(path)
|
|
26
|
+
async_path = trio.Path(path)
|
|
27
|
+
return getattr(sync_path, method_name), getattr(async_path, method_name)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
@pytest.mark.skipif(os.name == "nt", reason="OS is not posix")
|
|
31
|
+
def test_instantiate_posix() -> None:
|
|
32
|
+
assert isinstance(trio.Path(), trio.PosixPath)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
@pytest.mark.skipif(os.name != "nt", reason="OS is not Windows")
|
|
36
|
+
def test_instantiate_windows() -> None:
|
|
37
|
+
assert isinstance(trio.Path(), trio.WindowsPath)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
async def test_open_is_async_context_manager(path: trio.Path) -> None:
|
|
41
|
+
async with await path.open("w") as f:
|
|
42
|
+
assert isinstance(f, AsyncIOWrapper)
|
|
43
|
+
|
|
44
|
+
assert f.closed
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def test_magic() -> None:
|
|
48
|
+
path = trio.Path("test")
|
|
49
|
+
|
|
50
|
+
assert str(path) == "test"
|
|
51
|
+
assert bytes(path) == b"test"
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
EitherPathType = type[trio.Path] | type[pathlib.Path]
|
|
55
|
+
PathOrStrType = EitherPathType | type[str]
|
|
56
|
+
cls_pairs: list[tuple[EitherPathType, EitherPathType]] = [
|
|
57
|
+
(trio.Path, pathlib.Path),
|
|
58
|
+
(pathlib.Path, trio.Path),
|
|
59
|
+
(trio.Path, trio.Path),
|
|
60
|
+
]
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
@pytest.mark.parametrize(("cls_a", "cls_b"), cls_pairs)
|
|
64
|
+
def test_cmp_magic(cls_a: EitherPathType, cls_b: EitherPathType) -> None:
|
|
65
|
+
a, b = cls_a(""), cls_b("")
|
|
66
|
+
assert a == b
|
|
67
|
+
assert not a != b # noqa: SIM202 # negate-not-equal-op
|
|
68
|
+
|
|
69
|
+
a, b = cls_a("a"), cls_b("b")
|
|
70
|
+
assert a < b
|
|
71
|
+
assert b > a
|
|
72
|
+
|
|
73
|
+
# this is intentionally testing equivalence with none, due to the
|
|
74
|
+
# other=sentinel logic in _forward_magic
|
|
75
|
+
assert not a == None # noqa
|
|
76
|
+
assert not b == None # noqa
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
# upstream python3.8 bug: we should also test (pathlib.Path, trio.Path), but
|
|
80
|
+
# __*div__ does not properly raise NotImplementedError like the other comparison
|
|
81
|
+
# magic, so trio.Path's implementation does not get dispatched
|
|
82
|
+
cls_pairs_str: list[tuple[PathOrStrType, PathOrStrType]] = [
|
|
83
|
+
(trio.Path, pathlib.Path),
|
|
84
|
+
(trio.Path, trio.Path),
|
|
85
|
+
(trio.Path, str),
|
|
86
|
+
(str, trio.Path),
|
|
87
|
+
]
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
@pytest.mark.parametrize(("cls_a", "cls_b"), cls_pairs_str)
|
|
91
|
+
def test_div_magic(cls_a: PathOrStrType, cls_b: PathOrStrType) -> None:
|
|
92
|
+
a, b = cls_a("a"), cls_b("b")
|
|
93
|
+
|
|
94
|
+
result = a / b # type: ignore[operator]
|
|
95
|
+
# Type checkers think str / str could happen. Check each combo manually in type_tests/.
|
|
96
|
+
assert isinstance(result, trio.Path)
|
|
97
|
+
assert str(result) == os.path.join("a", "b")
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
@pytest.mark.parametrize(
|
|
101
|
+
("cls_a", "cls_b"),
|
|
102
|
+
[(trio.Path, pathlib.Path), (trio.Path, trio.Path)],
|
|
103
|
+
)
|
|
104
|
+
@pytest.mark.parametrize("path", ["foo", "foo/bar/baz", "./foo"])
|
|
105
|
+
def test_hash_magic(
|
|
106
|
+
cls_a: EitherPathType,
|
|
107
|
+
cls_b: EitherPathType,
|
|
108
|
+
path: str,
|
|
109
|
+
) -> None:
|
|
110
|
+
a, b = cls_a(path), cls_b(path)
|
|
111
|
+
assert hash(a) == hash(b)
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def test_forwarded_properties(path: trio.Path) -> None:
|
|
115
|
+
# use `name` as a representative of forwarded properties
|
|
116
|
+
|
|
117
|
+
assert "name" in dir(path)
|
|
118
|
+
assert path.name == "test"
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
def test_async_method_signature(path: trio.Path) -> None:
|
|
122
|
+
# use `resolve` as a representative of wrapped methods
|
|
123
|
+
|
|
124
|
+
assert path.resolve.__name__ == "resolve"
|
|
125
|
+
assert path.resolve.__qualname__ == "Path.resolve"
|
|
126
|
+
|
|
127
|
+
assert path.resolve.__doc__ is not None
|
|
128
|
+
assert path.resolve.__qualname__ in path.resolve.__doc__
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
@pytest.mark.parametrize("method_name", ["is_dir", "is_file"])
|
|
132
|
+
async def test_compare_async_stat_methods(method_name: str) -> None:
|
|
133
|
+
method, async_method = method_pair(".", method_name)
|
|
134
|
+
|
|
135
|
+
result = method()
|
|
136
|
+
async_result = await async_method()
|
|
137
|
+
|
|
138
|
+
assert result == async_result
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
def test_invalid_name_not_wrapped(path: trio.Path) -> None:
|
|
142
|
+
with pytest.raises(AttributeError):
|
|
143
|
+
getattr(path, "invalid_fake_attr") # noqa: B009 # "get-attr-with-constant"
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
@pytest.mark.parametrize("method_name", ["absolute", "resolve"])
|
|
147
|
+
async def test_async_methods_rewrap(method_name: str) -> None:
|
|
148
|
+
method, async_method = method_pair(".", method_name)
|
|
149
|
+
|
|
150
|
+
result = method()
|
|
151
|
+
async_result = await async_method()
|
|
152
|
+
|
|
153
|
+
assert isinstance(async_result, trio.Path)
|
|
154
|
+
assert str(result) == str(async_result)
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
def test_forward_methods_rewrap(path: trio.Path, tmp_path: pathlib.Path) -> None:
|
|
158
|
+
with_name = path.with_name("foo")
|
|
159
|
+
with_suffix = path.with_suffix(".py")
|
|
160
|
+
|
|
161
|
+
assert isinstance(with_name, trio.Path)
|
|
162
|
+
assert with_name == tmp_path / "foo"
|
|
163
|
+
assert isinstance(with_suffix, trio.Path)
|
|
164
|
+
assert with_suffix == tmp_path / "test.py"
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
def test_forward_properties_rewrap(path: trio.Path) -> None:
|
|
168
|
+
assert isinstance(path.parent, trio.Path)
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
def test_forward_methods_without_rewrap(path: trio.Path) -> None:
|
|
172
|
+
assert "totally-unique-path" in str(path.joinpath("totally-unique-path"))
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
def test_repr() -> None:
|
|
176
|
+
path = trio.Path(".")
|
|
177
|
+
|
|
178
|
+
assert repr(path) == "trio.Path('.')"
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
@pytest.mark.parametrize("meth", [trio.Path.__init__, trio.Path.joinpath])
|
|
182
|
+
async def test_path_wraps_path(
|
|
183
|
+
path: trio.Path,
|
|
184
|
+
meth: Callable[[trio.Path, trio.Path], object],
|
|
185
|
+
) -> None:
|
|
186
|
+
wrapped = await path.absolute()
|
|
187
|
+
result = meth(path, wrapped)
|
|
188
|
+
if result is None:
|
|
189
|
+
result = path
|
|
190
|
+
|
|
191
|
+
assert wrapped == result
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
def test_path_nonpath() -> None:
|
|
195
|
+
with pytest.raises(TypeError):
|
|
196
|
+
trio.Path(1) # type: ignore
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
async def test_open_file_can_open_path(path: trio.Path) -> None:
|
|
200
|
+
async with await trio.open_file(path, "w") as f:
|
|
201
|
+
assert f.name == os.fspath(path)
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
async def test_globmethods(path: trio.Path) -> None:
|
|
205
|
+
# Populate a directory tree
|
|
206
|
+
await path.mkdir()
|
|
207
|
+
await (path / "foo").mkdir()
|
|
208
|
+
await (path / "foo" / "_bar.txt").write_bytes(b"")
|
|
209
|
+
await (path / "bar.txt").write_bytes(b"")
|
|
210
|
+
await (path / "bar.dat").write_bytes(b"")
|
|
211
|
+
|
|
212
|
+
# Path.glob
|
|
213
|
+
for pattern, results in {
|
|
214
|
+
"*.txt": {"bar.txt"},
|
|
215
|
+
"**/*.txt": {"_bar.txt", "bar.txt"},
|
|
216
|
+
}.items():
|
|
217
|
+
entries = set()
|
|
218
|
+
for entry in await path.glob(pattern):
|
|
219
|
+
assert isinstance(entry, trio.Path)
|
|
220
|
+
entries.add(entry.name)
|
|
221
|
+
|
|
222
|
+
assert entries == results
|
|
223
|
+
|
|
224
|
+
# Path.rglob
|
|
225
|
+
entries = set()
|
|
226
|
+
for entry in await path.rglob("*.txt"):
|
|
227
|
+
assert isinstance(entry, trio.Path)
|
|
228
|
+
entries.add(entry.name)
|
|
229
|
+
|
|
230
|
+
assert entries == {"_bar.txt", "bar.txt"}
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
async def test_as_uri(path: trio.Path) -> None:
|
|
234
|
+
path = await path.parent.resolve()
|
|
235
|
+
|
|
236
|
+
assert path.as_uri().startswith("file:///")
|
|
237
|
+
|
|
238
|
+
|
|
239
|
+
async def test_iterdir(path: trio.Path) -> None:
|
|
240
|
+
# Populate a directory
|
|
241
|
+
await path.mkdir()
|
|
242
|
+
await (path / "foo").mkdir()
|
|
243
|
+
await (path / "bar.txt").write_bytes(b"")
|
|
244
|
+
|
|
245
|
+
entries = set()
|
|
246
|
+
for entry in await path.iterdir():
|
|
247
|
+
assert isinstance(entry, trio.Path)
|
|
248
|
+
entries.add(entry.name)
|
|
249
|
+
|
|
250
|
+
assert entries == {"bar.txt", "foo"}
|
|
251
|
+
|
|
252
|
+
|
|
253
|
+
async def test_classmethods() -> None:
|
|
254
|
+
assert isinstance(await trio.Path.home(), trio.Path)
|
|
255
|
+
|
|
256
|
+
# pathlib.Path has only two classmethods
|
|
257
|
+
assert str(await trio.Path.home()) == os.path.expanduser("~") # noqa: ASYNC240
|
|
258
|
+
assert str(await trio.Path.cwd()) == os.getcwd()
|
|
259
|
+
|
|
260
|
+
# Wrapped method has docstring
|
|
261
|
+
assert trio.Path.home.__doc__
|
|
262
|
+
|
|
263
|
+
|
|
264
|
+
@pytest.mark.parametrize(
|
|
265
|
+
"wrapper",
|
|
266
|
+
[
|
|
267
|
+
trio._path._wraps_async,
|
|
268
|
+
trio._path._wrap_method,
|
|
269
|
+
trio._path._wrap_method_path,
|
|
270
|
+
trio._path._wrap_method_path_iterable,
|
|
271
|
+
],
|
|
272
|
+
)
|
|
273
|
+
def test_wrapping_without_docstrings(
|
|
274
|
+
wrapper: Callable[[Callable[[], None]], Callable[[], None]],
|
|
275
|
+
) -> None:
|
|
276
|
+
@wrapper
|
|
277
|
+
def func_without_docstring() -> None: ... # pragma: no cover
|
|
278
|
+
|
|
279
|
+
assert func_without_docstring.__doc__ is None
|