@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,349 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import sys
|
|
4
|
+
import types
|
|
5
|
+
from typing import TYPE_CHECKING, TypeVar
|
|
6
|
+
|
|
7
|
+
if TYPE_CHECKING:
|
|
8
|
+
from collections.abc import AsyncGenerator, Coroutine, Generator
|
|
9
|
+
import pytest
|
|
10
|
+
|
|
11
|
+
import trio
|
|
12
|
+
from trio.testing import _Matcher as Matcher, _RaisesGroup as RaisesGroup
|
|
13
|
+
|
|
14
|
+
from .. import _core
|
|
15
|
+
from .._core._tests.tutil import (
|
|
16
|
+
create_asyncio_future_in_new_loop,
|
|
17
|
+
ignore_coroutine_never_awaited_warnings,
|
|
18
|
+
)
|
|
19
|
+
from .._util import (
|
|
20
|
+
ConflictDetector,
|
|
21
|
+
MultipleExceptionError,
|
|
22
|
+
NoPublicConstructor,
|
|
23
|
+
coroutine_or_error,
|
|
24
|
+
final,
|
|
25
|
+
fixup_module_metadata,
|
|
26
|
+
is_main_thread,
|
|
27
|
+
raise_single_exception_from_group,
|
|
28
|
+
)
|
|
29
|
+
from ..testing import wait_all_tasks_blocked
|
|
30
|
+
|
|
31
|
+
if sys.version_info < (3, 11):
|
|
32
|
+
from exceptiongroup import BaseExceptionGroup, ExceptionGroup
|
|
33
|
+
|
|
34
|
+
if TYPE_CHECKING:
|
|
35
|
+
from collections.abc import AsyncGenerator
|
|
36
|
+
|
|
37
|
+
T = TypeVar("T")
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
async def test_ConflictDetector() -> None:
|
|
41
|
+
ul1 = ConflictDetector("ul1")
|
|
42
|
+
ul2 = ConflictDetector("ul2")
|
|
43
|
+
|
|
44
|
+
with ul1:
|
|
45
|
+
with ul2:
|
|
46
|
+
print("ok")
|
|
47
|
+
|
|
48
|
+
with pytest.raises(_core.BusyResourceError, match="ul1"):
|
|
49
|
+
with ul1:
|
|
50
|
+
with ul1:
|
|
51
|
+
pass # pragma: no cover
|
|
52
|
+
|
|
53
|
+
async def wait_with_ul1() -> None:
|
|
54
|
+
with ul1:
|
|
55
|
+
await wait_all_tasks_blocked()
|
|
56
|
+
|
|
57
|
+
with RaisesGroup(Matcher(_core.BusyResourceError, "ul1")):
|
|
58
|
+
async with _core.open_nursery() as nursery:
|
|
59
|
+
nursery.start_soon(wait_with_ul1)
|
|
60
|
+
nursery.start_soon(wait_with_ul1)
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def test_module_metadata_is_fixed_up() -> None:
|
|
64
|
+
import trio
|
|
65
|
+
import trio.testing
|
|
66
|
+
|
|
67
|
+
assert trio.Cancelled.__module__ == "trio"
|
|
68
|
+
assert trio.open_nursery.__module__ == "trio"
|
|
69
|
+
assert trio.abc.Stream.__module__ == "trio.abc"
|
|
70
|
+
assert trio.lowlevel.wait_task_rescheduled.__module__ == "trio.lowlevel"
|
|
71
|
+
assert trio.testing.trio_test.__module__ == "trio.testing"
|
|
72
|
+
|
|
73
|
+
# Also check methods
|
|
74
|
+
assert trio.lowlevel.ParkingLot.__init__.__module__ == "trio.lowlevel"
|
|
75
|
+
assert trio.abc.Stream.send_all.__module__ == "trio.abc"
|
|
76
|
+
|
|
77
|
+
# And names
|
|
78
|
+
assert trio.Cancelled.__name__ == "Cancelled"
|
|
79
|
+
assert trio.Cancelled.__qualname__ == "Cancelled"
|
|
80
|
+
assert trio.abc.SendStream.send_all.__name__ == "send_all"
|
|
81
|
+
assert trio.abc.SendStream.send_all.__qualname__ == "SendStream.send_all"
|
|
82
|
+
assert trio.to_thread.__name__ == "trio.to_thread"
|
|
83
|
+
assert trio.to_thread.run_sync.__name__ == "run_sync"
|
|
84
|
+
assert trio.to_thread.run_sync.__qualname__ == "run_sync"
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
async def test_is_main_thread() -> None:
|
|
88
|
+
assert is_main_thread()
|
|
89
|
+
|
|
90
|
+
def not_main_thread() -> None:
|
|
91
|
+
assert not is_main_thread()
|
|
92
|
+
|
|
93
|
+
await trio.to_thread.run_sync(not_main_thread)
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
# @coroutine is deprecated since python 3.8, which is fine with us.
|
|
97
|
+
@pytest.mark.filterwarnings("ignore:.*@coroutine.*:DeprecationWarning")
|
|
98
|
+
def test_coroutine_or_error() -> None:
|
|
99
|
+
class Deferred:
|
|
100
|
+
"Just kidding"
|
|
101
|
+
|
|
102
|
+
with ignore_coroutine_never_awaited_warnings():
|
|
103
|
+
|
|
104
|
+
async def f() -> None: # pragma: no cover
|
|
105
|
+
pass
|
|
106
|
+
|
|
107
|
+
with pytest.raises(TypeError) as excinfo:
|
|
108
|
+
coroutine_or_error(f()) # type: ignore[arg-type, unused-coroutine]
|
|
109
|
+
assert "expecting an async function" in str(excinfo.value)
|
|
110
|
+
|
|
111
|
+
import asyncio
|
|
112
|
+
|
|
113
|
+
if sys.version_info < (3, 11):
|
|
114
|
+
|
|
115
|
+
@asyncio.coroutine
|
|
116
|
+
def generator_based_coro() -> (
|
|
117
|
+
Generator[Coroutine[None, None, None], None, None]
|
|
118
|
+
): # pragma: no cover
|
|
119
|
+
yield from asyncio.sleep(1)
|
|
120
|
+
|
|
121
|
+
with pytest.raises(TypeError) as excinfo:
|
|
122
|
+
coroutine_or_error(generator_based_coro()) # type: ignore[arg-type, unused-coroutine]
|
|
123
|
+
assert "asyncio" in str(excinfo.value)
|
|
124
|
+
|
|
125
|
+
with pytest.raises(TypeError) as excinfo:
|
|
126
|
+
coroutine_or_error(create_asyncio_future_in_new_loop()) # type: ignore[arg-type, unused-coroutine]
|
|
127
|
+
assert "asyncio" in str(excinfo.value)
|
|
128
|
+
|
|
129
|
+
# does not raise arg-type error
|
|
130
|
+
with pytest.raises(TypeError) as excinfo:
|
|
131
|
+
coroutine_or_error(create_asyncio_future_in_new_loop) # type: ignore[unused-coroutine]
|
|
132
|
+
assert "asyncio" in str(excinfo.value)
|
|
133
|
+
|
|
134
|
+
with pytest.raises(TypeError) as excinfo:
|
|
135
|
+
coroutine_or_error(Deferred()) # type: ignore[arg-type, unused-coroutine]
|
|
136
|
+
assert "twisted" in str(excinfo.value)
|
|
137
|
+
|
|
138
|
+
with pytest.raises(TypeError) as excinfo:
|
|
139
|
+
coroutine_or_error(lambda: Deferred()) # type: ignore[arg-type, unused-coroutine, return-value]
|
|
140
|
+
assert "twisted" in str(excinfo.value)
|
|
141
|
+
|
|
142
|
+
with pytest.raises(TypeError) as excinfo:
|
|
143
|
+
coroutine_or_error(len, [[1, 2, 3]]) # type: ignore[arg-type, unused-coroutine]
|
|
144
|
+
|
|
145
|
+
assert "appears to be synchronous" in str(excinfo.value)
|
|
146
|
+
|
|
147
|
+
async def async_gen(
|
|
148
|
+
_: object,
|
|
149
|
+
) -> AsyncGenerator[None, None]: # pragma: no cover
|
|
150
|
+
yield
|
|
151
|
+
|
|
152
|
+
with pytest.raises(TypeError) as excinfo:
|
|
153
|
+
coroutine_or_error(async_gen, [0]) # type: ignore[arg-type,unused-coroutine]
|
|
154
|
+
msg = "expected an async function but got an async generator"
|
|
155
|
+
assert msg in str(excinfo.value)
|
|
156
|
+
|
|
157
|
+
# Make sure no references are kept around to keep anything alive
|
|
158
|
+
del excinfo
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
def test_final_decorator() -> None:
|
|
162
|
+
"""Test that subclassing a @final-annotated class is not allowed.
|
|
163
|
+
|
|
164
|
+
This checks both runtime results, and verifies that type checkers detect
|
|
165
|
+
the error statically through the type-ignore comment.
|
|
166
|
+
"""
|
|
167
|
+
|
|
168
|
+
@final
|
|
169
|
+
class FinalClass:
|
|
170
|
+
pass
|
|
171
|
+
|
|
172
|
+
with pytest.raises(TypeError):
|
|
173
|
+
|
|
174
|
+
class SubClass(FinalClass): # type: ignore[misc]
|
|
175
|
+
pass
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
def test_no_public_constructor_metaclass() -> None:
|
|
179
|
+
"""The NoPublicConstructor metaclass prevents calling the constructor directly."""
|
|
180
|
+
|
|
181
|
+
class SpecialClass(metaclass=NoPublicConstructor):
|
|
182
|
+
def __init__(self, a: int, b: float) -> None:
|
|
183
|
+
"""Check arguments can be passed to __init__."""
|
|
184
|
+
assert a == 8
|
|
185
|
+
assert b == 3.15
|
|
186
|
+
|
|
187
|
+
with pytest.raises(TypeError):
|
|
188
|
+
SpecialClass(8, 3.15)
|
|
189
|
+
|
|
190
|
+
# Private constructor should not raise, and passes args to __init__.
|
|
191
|
+
assert isinstance(SpecialClass._create(8, b=3.15), SpecialClass)
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
def test_fixup_module_metadata() -> None:
|
|
195
|
+
# Ignores modules not in the trio.X tree.
|
|
196
|
+
non_trio_module = types.ModuleType("not_trio")
|
|
197
|
+
non_trio_module.some_func = lambda: None # type: ignore[attr-defined]
|
|
198
|
+
non_trio_module.some_func.__name__ = "some_func"
|
|
199
|
+
non_trio_module.some_func.__qualname__ = "some_func"
|
|
200
|
+
|
|
201
|
+
fixup_module_metadata(non_trio_module.__name__, vars(non_trio_module))
|
|
202
|
+
|
|
203
|
+
assert non_trio_module.some_func.__name__ == "some_func"
|
|
204
|
+
assert non_trio_module.some_func.__qualname__ == "some_func"
|
|
205
|
+
|
|
206
|
+
# Bulild up a fake module to test. Just use lambdas since all we care about is the names.
|
|
207
|
+
mod = types.ModuleType("trio._somemodule_impl")
|
|
208
|
+
mod.some_func = lambda: None # type: ignore[attr-defined]
|
|
209
|
+
mod.some_func.__name__ = "_something_else"
|
|
210
|
+
mod.some_func.__qualname__ = "_something_else"
|
|
211
|
+
|
|
212
|
+
# No __module__ means it's unchanged.
|
|
213
|
+
mod.not_funclike = types.SimpleNamespace() # type: ignore[attr-defined]
|
|
214
|
+
mod.not_funclike.__name__ = "not_funclike"
|
|
215
|
+
|
|
216
|
+
# Check __qualname__ being absent works.
|
|
217
|
+
mod.only_has_name = types.SimpleNamespace() # type: ignore[attr-defined]
|
|
218
|
+
mod.only_has_name.__module__ = "trio._somemodule_impl"
|
|
219
|
+
mod.only_has_name.__name__ = "only_name"
|
|
220
|
+
|
|
221
|
+
# Underscored names are unchanged.
|
|
222
|
+
mod._private = lambda: None # type: ignore[attr-defined]
|
|
223
|
+
mod._private.__module__ = "trio._somemodule_impl"
|
|
224
|
+
mod._private.__name__ = mod._private.__qualname__ = "_private"
|
|
225
|
+
|
|
226
|
+
# We recurse into classes.
|
|
227
|
+
mod.SomeClass = type( # type: ignore[attr-defined]
|
|
228
|
+
"SomeClass",
|
|
229
|
+
(),
|
|
230
|
+
{
|
|
231
|
+
"__init__": lambda self: None,
|
|
232
|
+
"method": lambda self: None,
|
|
233
|
+
},
|
|
234
|
+
)
|
|
235
|
+
# Reference loop is fine.
|
|
236
|
+
mod.SomeClass.recursion = mod.SomeClass
|
|
237
|
+
|
|
238
|
+
fixup_module_metadata("trio.somemodule", vars(mod))
|
|
239
|
+
assert mod.some_func.__name__ == "some_func"
|
|
240
|
+
assert mod.some_func.__module__ == "trio.somemodule"
|
|
241
|
+
assert mod.some_func.__qualname__ == "some_func"
|
|
242
|
+
|
|
243
|
+
assert mod.not_funclike.__name__ == "not_funclike"
|
|
244
|
+
assert mod._private.__name__ == "_private"
|
|
245
|
+
assert mod._private.__module__ == "trio._somemodule_impl"
|
|
246
|
+
assert mod._private.__qualname__ == "_private"
|
|
247
|
+
|
|
248
|
+
assert mod.only_has_name.__name__ == "only_has_name"
|
|
249
|
+
assert mod.only_has_name.__module__ == "trio.somemodule"
|
|
250
|
+
assert not hasattr(mod.only_has_name, "__qualname__")
|
|
251
|
+
|
|
252
|
+
assert mod.SomeClass.method.__name__ == "method"
|
|
253
|
+
assert mod.SomeClass.method.__module__ == "trio.somemodule"
|
|
254
|
+
assert mod.SomeClass.method.__qualname__ == "SomeClass.method"
|
|
255
|
+
# Make coverage happy.
|
|
256
|
+
non_trio_module.some_func()
|
|
257
|
+
mod.some_func()
|
|
258
|
+
mod._private()
|
|
259
|
+
mod.SomeClass().method()
|
|
260
|
+
|
|
261
|
+
|
|
262
|
+
async def test_raise_single_exception_from_group() -> None:
|
|
263
|
+
excinfo: pytest.ExceptionInfo[BaseException]
|
|
264
|
+
|
|
265
|
+
exc = ValueError("foo")
|
|
266
|
+
cause = SyntaxError("cause")
|
|
267
|
+
context = TypeError("context")
|
|
268
|
+
exc.__cause__ = cause
|
|
269
|
+
exc.__context__ = context
|
|
270
|
+
cancelled = trio.Cancelled._create(source="deadline")
|
|
271
|
+
|
|
272
|
+
with pytest.raises(ValueError, match="foo") as excinfo:
|
|
273
|
+
raise_single_exception_from_group(ExceptionGroup("", [exc]))
|
|
274
|
+
assert excinfo.value.__cause__ == cause
|
|
275
|
+
assert excinfo.value.__context__ == context
|
|
276
|
+
|
|
277
|
+
# only unwraps one layer of exceptiongroup
|
|
278
|
+
inner_eg = ExceptionGroup("inner eg", [exc])
|
|
279
|
+
inner_cause = SyntaxError("inner eg cause")
|
|
280
|
+
inner_context = TypeError("inner eg context")
|
|
281
|
+
inner_eg.__cause__ = inner_cause
|
|
282
|
+
inner_eg.__context__ = inner_context
|
|
283
|
+
with RaisesGroup(Matcher(ValueError, match="^foo$"), match="^inner eg$") as eginfo:
|
|
284
|
+
raise_single_exception_from_group(ExceptionGroup("", [inner_eg]))
|
|
285
|
+
assert eginfo.value.__cause__ == inner_cause
|
|
286
|
+
assert eginfo.value.__context__ == inner_context
|
|
287
|
+
|
|
288
|
+
with pytest.raises(ValueError, match="foo") as excinfo:
|
|
289
|
+
raise_single_exception_from_group(
|
|
290
|
+
BaseExceptionGroup("", [cancelled, cancelled, exc])
|
|
291
|
+
)
|
|
292
|
+
assert excinfo.value.__cause__ == cause
|
|
293
|
+
assert excinfo.value.__context__ == context
|
|
294
|
+
|
|
295
|
+
# multiple non-cancelled
|
|
296
|
+
eg = ExceptionGroup("", [ValueError("foo"), ValueError("bar")])
|
|
297
|
+
with pytest.raises(
|
|
298
|
+
MultipleExceptionError,
|
|
299
|
+
match=r"^Attempted to unwrap exceptiongroup with multiple non-cancelled exceptions. This is often caused by a bug in the caller.$",
|
|
300
|
+
) as excinfo:
|
|
301
|
+
raise_single_exception_from_group(eg)
|
|
302
|
+
assert excinfo.value.__cause__ is eg
|
|
303
|
+
assert excinfo.value.__context__ is None
|
|
304
|
+
|
|
305
|
+
# keyboardinterrupt overrides everything
|
|
306
|
+
eg_ki = BaseExceptionGroup(
|
|
307
|
+
"",
|
|
308
|
+
[
|
|
309
|
+
ValueError("foo"),
|
|
310
|
+
ValueError("bar"),
|
|
311
|
+
KeyboardInterrupt("preserve error msg"),
|
|
312
|
+
],
|
|
313
|
+
)
|
|
314
|
+
with pytest.raises(
|
|
315
|
+
KeyboardInterrupt,
|
|
316
|
+
match=r"^preserve error msg$",
|
|
317
|
+
) as excinfo:
|
|
318
|
+
raise_single_exception_from_group(eg_ki)
|
|
319
|
+
|
|
320
|
+
assert excinfo.value.__cause__ is eg_ki
|
|
321
|
+
assert excinfo.value.__context__ is None
|
|
322
|
+
|
|
323
|
+
# and same for SystemExit but verify code too
|
|
324
|
+
systemexit_ki = BaseExceptionGroup(
|
|
325
|
+
"",
|
|
326
|
+
[
|
|
327
|
+
ValueError("foo"),
|
|
328
|
+
ValueError("bar"),
|
|
329
|
+
SystemExit(2),
|
|
330
|
+
],
|
|
331
|
+
)
|
|
332
|
+
|
|
333
|
+
with pytest.raises(SystemExit) as excinfo:
|
|
334
|
+
raise_single_exception_from_group(systemexit_ki)
|
|
335
|
+
|
|
336
|
+
assert excinfo.value.code == 2
|
|
337
|
+
assert excinfo.value.__cause__ is systemexit_ki
|
|
338
|
+
assert excinfo.value.__context__ is None
|
|
339
|
+
|
|
340
|
+
# if we only got cancelled, first one is reraised
|
|
341
|
+
with pytest.raises(trio.Cancelled, match=r"^cancelled due to deadline$") as excinfo:
|
|
342
|
+
raise_single_exception_from_group(
|
|
343
|
+
BaseExceptionGroup(
|
|
344
|
+
"", [cancelled, trio.Cancelled._create(source="explicit")]
|
|
345
|
+
)
|
|
346
|
+
)
|
|
347
|
+
assert excinfo.value is cancelled
|
|
348
|
+
assert excinfo.value.__cause__ is None
|
|
349
|
+
assert excinfo.value.__context__ is None
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
import os
|
|
2
|
+
|
|
3
|
+
import pytest
|
|
4
|
+
|
|
5
|
+
on_windows = os.name == "nt"
|
|
6
|
+
# Mark all the tests in this file as being windows-only
|
|
7
|
+
pytestmark = pytest.mark.skipif(not on_windows, reason="windows only")
|
|
8
|
+
|
|
9
|
+
import trio
|
|
10
|
+
|
|
11
|
+
from .. import _core, _timeouts
|
|
12
|
+
from .._core._tests.tutil import slow
|
|
13
|
+
|
|
14
|
+
if on_windows:
|
|
15
|
+
from .._core._windows_cffi import Handle, ffi, kernel32
|
|
16
|
+
from .._wait_for_object import WaitForMultipleObjects_sync, WaitForSingleObject
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def test_WaitForMultipleObjects_sync() -> None:
|
|
20
|
+
# This does a series of tests where we set/close the handle before
|
|
21
|
+
# initiating the waiting for it.
|
|
22
|
+
#
|
|
23
|
+
# Note that closing the handle (not signaling) will cause the
|
|
24
|
+
# *initiation* of a wait to return immediately. But closing a handle
|
|
25
|
+
# that is already being waited on will not stop whatever is waiting
|
|
26
|
+
# for it.
|
|
27
|
+
|
|
28
|
+
# One handle
|
|
29
|
+
handle1 = kernel32.CreateEventA(ffi.NULL, True, False, ffi.NULL)
|
|
30
|
+
kernel32.SetEvent(handle1)
|
|
31
|
+
WaitForMultipleObjects_sync(handle1)
|
|
32
|
+
kernel32.CloseHandle(handle1)
|
|
33
|
+
print("test_WaitForMultipleObjects_sync one OK")
|
|
34
|
+
|
|
35
|
+
# Two handles, signal first
|
|
36
|
+
handle1 = kernel32.CreateEventA(ffi.NULL, True, False, ffi.NULL)
|
|
37
|
+
handle2 = kernel32.CreateEventA(ffi.NULL, True, False, ffi.NULL)
|
|
38
|
+
kernel32.SetEvent(handle1)
|
|
39
|
+
WaitForMultipleObjects_sync(handle1, handle2)
|
|
40
|
+
kernel32.CloseHandle(handle1)
|
|
41
|
+
kernel32.CloseHandle(handle2)
|
|
42
|
+
print("test_WaitForMultipleObjects_sync set first OK")
|
|
43
|
+
|
|
44
|
+
# Two handles, signal second
|
|
45
|
+
handle1 = kernel32.CreateEventA(ffi.NULL, True, False, ffi.NULL)
|
|
46
|
+
handle2 = kernel32.CreateEventA(ffi.NULL, True, False, ffi.NULL)
|
|
47
|
+
kernel32.SetEvent(handle2)
|
|
48
|
+
WaitForMultipleObjects_sync(handle1, handle2)
|
|
49
|
+
kernel32.CloseHandle(handle1)
|
|
50
|
+
kernel32.CloseHandle(handle2)
|
|
51
|
+
print("test_WaitForMultipleObjects_sync set second OK")
|
|
52
|
+
|
|
53
|
+
# Two handles, close first
|
|
54
|
+
handle1 = kernel32.CreateEventA(ffi.NULL, True, False, ffi.NULL)
|
|
55
|
+
handle2 = kernel32.CreateEventA(ffi.NULL, True, False, ffi.NULL)
|
|
56
|
+
kernel32.CloseHandle(handle1)
|
|
57
|
+
with pytest.raises(OSError, match=r"^\[WinError 6\] The handle is invalid$"):
|
|
58
|
+
WaitForMultipleObjects_sync(handle1, handle2)
|
|
59
|
+
kernel32.CloseHandle(handle2)
|
|
60
|
+
print("test_WaitForMultipleObjects_sync close first OK")
|
|
61
|
+
|
|
62
|
+
# Two handles, close second
|
|
63
|
+
handle1 = kernel32.CreateEventA(ffi.NULL, True, False, ffi.NULL)
|
|
64
|
+
handle2 = kernel32.CreateEventA(ffi.NULL, True, False, ffi.NULL)
|
|
65
|
+
kernel32.CloseHandle(handle2)
|
|
66
|
+
with pytest.raises(OSError, match=r"^\[WinError 6\] The handle is invalid$"):
|
|
67
|
+
WaitForMultipleObjects_sync(handle1, handle2)
|
|
68
|
+
kernel32.CloseHandle(handle1)
|
|
69
|
+
print("test_WaitForMultipleObjects_sync close second OK")
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
@slow
|
|
73
|
+
async def test_WaitForMultipleObjects_sync_slow() -> None:
|
|
74
|
+
# This does a series of test in which the main thread sync-waits for
|
|
75
|
+
# handles, while we spawn a thread to set the handles after a short while.
|
|
76
|
+
|
|
77
|
+
TIMEOUT = 0.3
|
|
78
|
+
|
|
79
|
+
# One handle
|
|
80
|
+
handle1 = kernel32.CreateEventA(ffi.NULL, True, False, ffi.NULL)
|
|
81
|
+
t0 = _core.current_time()
|
|
82
|
+
async with _core.open_nursery() as nursery:
|
|
83
|
+
nursery.start_soon(
|
|
84
|
+
trio.to_thread.run_sync,
|
|
85
|
+
WaitForMultipleObjects_sync,
|
|
86
|
+
handle1,
|
|
87
|
+
)
|
|
88
|
+
await _timeouts.sleep(TIMEOUT)
|
|
89
|
+
# If we would comment the line below, the above thread will be stuck,
|
|
90
|
+
# and Trio won't exit this scope
|
|
91
|
+
kernel32.SetEvent(handle1)
|
|
92
|
+
t1 = _core.current_time()
|
|
93
|
+
assert TIMEOUT <= (t1 - t0) < 2.0 * TIMEOUT
|
|
94
|
+
kernel32.CloseHandle(handle1)
|
|
95
|
+
print("test_WaitForMultipleObjects_sync_slow one OK")
|
|
96
|
+
|
|
97
|
+
# Two handles, signal first
|
|
98
|
+
handle1 = kernel32.CreateEventA(ffi.NULL, True, False, ffi.NULL)
|
|
99
|
+
handle2 = kernel32.CreateEventA(ffi.NULL, True, False, ffi.NULL)
|
|
100
|
+
t0 = _core.current_time()
|
|
101
|
+
async with _core.open_nursery() as nursery:
|
|
102
|
+
nursery.start_soon(
|
|
103
|
+
trio.to_thread.run_sync,
|
|
104
|
+
WaitForMultipleObjects_sync,
|
|
105
|
+
handle1,
|
|
106
|
+
handle2,
|
|
107
|
+
)
|
|
108
|
+
await _timeouts.sleep(TIMEOUT)
|
|
109
|
+
kernel32.SetEvent(handle1)
|
|
110
|
+
t1 = _core.current_time()
|
|
111
|
+
assert TIMEOUT <= (t1 - t0) < 2.0 * TIMEOUT
|
|
112
|
+
kernel32.CloseHandle(handle1)
|
|
113
|
+
kernel32.CloseHandle(handle2)
|
|
114
|
+
print("test_WaitForMultipleObjects_sync_slow thread-set first OK")
|
|
115
|
+
|
|
116
|
+
# Two handles, signal second
|
|
117
|
+
handle1 = kernel32.CreateEventA(ffi.NULL, True, False, ffi.NULL)
|
|
118
|
+
handle2 = kernel32.CreateEventA(ffi.NULL, True, False, ffi.NULL)
|
|
119
|
+
t0 = _core.current_time()
|
|
120
|
+
async with _core.open_nursery() as nursery:
|
|
121
|
+
nursery.start_soon(
|
|
122
|
+
trio.to_thread.run_sync,
|
|
123
|
+
WaitForMultipleObjects_sync,
|
|
124
|
+
handle1,
|
|
125
|
+
handle2,
|
|
126
|
+
)
|
|
127
|
+
await _timeouts.sleep(TIMEOUT)
|
|
128
|
+
kernel32.SetEvent(handle2)
|
|
129
|
+
t1 = _core.current_time()
|
|
130
|
+
assert TIMEOUT <= (t1 - t0) < 2.0 * TIMEOUT
|
|
131
|
+
kernel32.CloseHandle(handle1)
|
|
132
|
+
kernel32.CloseHandle(handle2)
|
|
133
|
+
print("test_WaitForMultipleObjects_sync_slow thread-set second OK")
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
async def test_WaitForSingleObject() -> None:
|
|
137
|
+
# This does a series of test for setting/closing the handle before
|
|
138
|
+
# initiating the wait.
|
|
139
|
+
|
|
140
|
+
# Test already set
|
|
141
|
+
handle = kernel32.CreateEventA(ffi.NULL, True, False, ffi.NULL)
|
|
142
|
+
kernel32.SetEvent(handle)
|
|
143
|
+
await WaitForSingleObject(handle) # should return at once
|
|
144
|
+
kernel32.CloseHandle(handle)
|
|
145
|
+
print("test_WaitForSingleObject already set OK")
|
|
146
|
+
|
|
147
|
+
# Test already set, as int
|
|
148
|
+
handle = kernel32.CreateEventA(ffi.NULL, True, False, ffi.NULL)
|
|
149
|
+
handle_int = int(ffi.cast("intptr_t", handle))
|
|
150
|
+
kernel32.SetEvent(handle)
|
|
151
|
+
await WaitForSingleObject(handle_int) # should return at once
|
|
152
|
+
kernel32.CloseHandle(handle)
|
|
153
|
+
print("test_WaitForSingleObject already set OK")
|
|
154
|
+
|
|
155
|
+
# Test already closed
|
|
156
|
+
handle = kernel32.CreateEventA(ffi.NULL, True, False, ffi.NULL)
|
|
157
|
+
kernel32.CloseHandle(handle)
|
|
158
|
+
with pytest.raises(OSError, match=r"^\[WinError 6\] The handle is invalid$"):
|
|
159
|
+
await WaitForSingleObject(handle) # should return at once
|
|
160
|
+
print("test_WaitForSingleObject already closed OK")
|
|
161
|
+
|
|
162
|
+
# Not a handle
|
|
163
|
+
with pytest.raises(TypeError):
|
|
164
|
+
await WaitForSingleObject("not a handle") # type: ignore[arg-type] # Wrong type
|
|
165
|
+
# with pytest.raises(OSError):
|
|
166
|
+
# await WaitForSingleObject(99) # If you're unlucky, it actually IS a handle :(
|
|
167
|
+
print("test_WaitForSingleObject not a handle OK")
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
@slow
|
|
171
|
+
async def test_WaitForSingleObject_slow() -> None:
|
|
172
|
+
# This does a series of test for setting the handle in another task,
|
|
173
|
+
# and cancelling the wait task.
|
|
174
|
+
|
|
175
|
+
# Set the timeout used in the tests. We test the waiting time against
|
|
176
|
+
# the timeout with a certain margin.
|
|
177
|
+
TIMEOUT = 0.3
|
|
178
|
+
|
|
179
|
+
async def signal_soon_async(handle: Handle) -> None:
|
|
180
|
+
await _timeouts.sleep(TIMEOUT)
|
|
181
|
+
kernel32.SetEvent(handle)
|
|
182
|
+
|
|
183
|
+
# Test handle is SET after TIMEOUT in separate coroutine
|
|
184
|
+
|
|
185
|
+
handle = kernel32.CreateEventA(ffi.NULL, True, False, ffi.NULL)
|
|
186
|
+
t0 = _core.current_time()
|
|
187
|
+
|
|
188
|
+
async with _core.open_nursery() as nursery:
|
|
189
|
+
nursery.start_soon(WaitForSingleObject, handle)
|
|
190
|
+
nursery.start_soon(signal_soon_async, handle)
|
|
191
|
+
|
|
192
|
+
kernel32.CloseHandle(handle)
|
|
193
|
+
t1 = _core.current_time()
|
|
194
|
+
assert TIMEOUT <= (t1 - t0) < 2.0 * TIMEOUT
|
|
195
|
+
print("test_WaitForSingleObject_slow set from task OK")
|
|
196
|
+
|
|
197
|
+
# Test handle is SET after TIMEOUT in separate coroutine, as int
|
|
198
|
+
|
|
199
|
+
handle = kernel32.CreateEventA(ffi.NULL, True, False, ffi.NULL)
|
|
200
|
+
handle_int = int(ffi.cast("intptr_t", handle))
|
|
201
|
+
t0 = _core.current_time()
|
|
202
|
+
|
|
203
|
+
async with _core.open_nursery() as nursery:
|
|
204
|
+
nursery.start_soon(WaitForSingleObject, handle_int)
|
|
205
|
+
nursery.start_soon(signal_soon_async, handle)
|
|
206
|
+
|
|
207
|
+
kernel32.CloseHandle(handle)
|
|
208
|
+
t1 = _core.current_time()
|
|
209
|
+
assert TIMEOUT <= (t1 - t0) < 2.0 * TIMEOUT
|
|
210
|
+
print("test_WaitForSingleObject_slow set from task as int OK")
|
|
211
|
+
|
|
212
|
+
# Test handle is CLOSED after 1 sec - NOPE see comment above
|
|
213
|
+
|
|
214
|
+
# Test cancellation
|
|
215
|
+
|
|
216
|
+
handle = kernel32.CreateEventA(ffi.NULL, True, False, ffi.NULL)
|
|
217
|
+
t0 = _core.current_time()
|
|
218
|
+
|
|
219
|
+
with _timeouts.move_on_after(TIMEOUT):
|
|
220
|
+
await WaitForSingleObject(handle)
|
|
221
|
+
|
|
222
|
+
kernel32.CloseHandle(handle)
|
|
223
|
+
t1 = _core.current_time()
|
|
224
|
+
assert TIMEOUT <= (t1 - t0) < 2.0 * TIMEOUT
|
|
225
|
+
print("test_WaitForSingleObject_slow cancellation OK")
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import sys
|
|
4
|
+
from typing import TYPE_CHECKING
|
|
5
|
+
|
|
6
|
+
import pytest
|
|
7
|
+
|
|
8
|
+
from .. import _core
|
|
9
|
+
from ..testing import check_one_way_stream, wait_all_tasks_blocked
|
|
10
|
+
|
|
11
|
+
# Mark all the tests in this file as being windows-only
|
|
12
|
+
pytestmark = pytest.mark.skipif(sys.platform != "win32", reason="windows only")
|
|
13
|
+
|
|
14
|
+
assert ( # Skip type checking when not on Windows
|
|
15
|
+
sys.platform == "win32" or not TYPE_CHECKING
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
if sys.platform == "win32":
|
|
19
|
+
from asyncio.windows_utils import pipe
|
|
20
|
+
|
|
21
|
+
from .._core._windows_cffi import _handle, kernel32
|
|
22
|
+
from .._windows_pipes import PipeReceiveStream, PipeSendStream
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
async def make_pipe() -> tuple[PipeSendStream, PipeReceiveStream]:
|
|
26
|
+
"""Makes a new pair of pipes."""
|
|
27
|
+
r, w = pipe()
|
|
28
|
+
return PipeSendStream(w), PipeReceiveStream(r)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def test_pipe_typecheck() -> None:
|
|
32
|
+
with pytest.raises(TypeError):
|
|
33
|
+
PipeSendStream(1.0) # type: ignore[arg-type]
|
|
34
|
+
with pytest.raises(TypeError):
|
|
35
|
+
PipeReceiveStream(None) # type: ignore[arg-type]
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
async def test_pipe_error_on_close() -> None:
|
|
39
|
+
# Make sure we correctly handle a failure from kernel32.CloseHandle
|
|
40
|
+
r, w = pipe()
|
|
41
|
+
|
|
42
|
+
send_stream = PipeSendStream(w)
|
|
43
|
+
receive_stream = PipeReceiveStream(r)
|
|
44
|
+
|
|
45
|
+
assert kernel32.CloseHandle(_handle(r))
|
|
46
|
+
assert kernel32.CloseHandle(_handle(w))
|
|
47
|
+
|
|
48
|
+
with pytest.raises(OSError, match=r"^\[WinError 6\] The handle is invalid$"):
|
|
49
|
+
await send_stream.aclose()
|
|
50
|
+
with pytest.raises(OSError, match=r"^\[WinError 6\] The handle is invalid$"):
|
|
51
|
+
await receive_stream.aclose()
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
async def test_pipes_combined() -> None:
|
|
55
|
+
write, read = await make_pipe()
|
|
56
|
+
count = 2**20
|
|
57
|
+
replicas = 3
|
|
58
|
+
|
|
59
|
+
async def sender() -> None:
|
|
60
|
+
async with write:
|
|
61
|
+
big = bytearray(count)
|
|
62
|
+
for _ in range(replicas):
|
|
63
|
+
await write.send_all(big)
|
|
64
|
+
|
|
65
|
+
async def reader() -> None:
|
|
66
|
+
async with read:
|
|
67
|
+
await wait_all_tasks_blocked()
|
|
68
|
+
total_received = 0
|
|
69
|
+
while True:
|
|
70
|
+
# 5000 is chosen because it doesn't evenly divide 2**20
|
|
71
|
+
received = len(await read.receive_some(5000))
|
|
72
|
+
if not received:
|
|
73
|
+
break
|
|
74
|
+
total_received += received
|
|
75
|
+
|
|
76
|
+
assert total_received == count * replicas
|
|
77
|
+
|
|
78
|
+
async with _core.open_nursery() as n:
|
|
79
|
+
n.start_soon(sender)
|
|
80
|
+
n.start_soon(reader)
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
async def test_async_with() -> None:
|
|
84
|
+
w, r = await make_pipe()
|
|
85
|
+
async with w, r:
|
|
86
|
+
pass
|
|
87
|
+
|
|
88
|
+
with pytest.raises(_core.ClosedResourceError):
|
|
89
|
+
await w.send_all(b"")
|
|
90
|
+
with pytest.raises(_core.ClosedResourceError):
|
|
91
|
+
await r.receive_some(10)
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
async def test_close_during_write() -> None:
|
|
95
|
+
w, _r = await make_pipe()
|
|
96
|
+
async with _core.open_nursery() as nursery:
|
|
97
|
+
|
|
98
|
+
async def write_forever() -> None:
|
|
99
|
+
with pytest.raises(_core.ClosedResourceError) as excinfo:
|
|
100
|
+
while True:
|
|
101
|
+
await w.send_all(b"x" * 4096)
|
|
102
|
+
assert "another task" in str(excinfo.value)
|
|
103
|
+
|
|
104
|
+
nursery.start_soon(write_forever)
|
|
105
|
+
await wait_all_tasks_blocked(0.1)
|
|
106
|
+
await w.aclose()
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
async def test_pipe_fully() -> None:
|
|
110
|
+
# passing make_clogged_pipe tests wait_send_all_might_not_block, and we
|
|
111
|
+
# can't implement that on Windows
|
|
112
|
+
await check_one_way_stream(make_pipe, None)
|
|
File without changes
|