@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,315 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import TYPE_CHECKING, NoReturn
|
|
4
|
+
|
|
5
|
+
import attrs
|
|
6
|
+
import pytest
|
|
7
|
+
|
|
8
|
+
from ... import _abc, _core
|
|
9
|
+
from .tutil import check_sequence_matches
|
|
10
|
+
|
|
11
|
+
if TYPE_CHECKING:
|
|
12
|
+
from collections.abc import Container, Iterable
|
|
13
|
+
|
|
14
|
+
from ...lowlevel import Task
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@attrs.define(eq=False, slots=False)
|
|
18
|
+
class TaskRecorder(_abc.Instrument):
|
|
19
|
+
record: list[tuple[str, Task | None]] = attrs.Factory(list)
|
|
20
|
+
|
|
21
|
+
def before_run(self) -> None:
|
|
22
|
+
self.record.append(("before_run", None))
|
|
23
|
+
|
|
24
|
+
def task_scheduled(self, task: Task) -> None:
|
|
25
|
+
self.record.append(("schedule", task))
|
|
26
|
+
|
|
27
|
+
def before_task_step(self, task: Task) -> None:
|
|
28
|
+
assert task is _core.current_task()
|
|
29
|
+
self.record.append(("before", task))
|
|
30
|
+
|
|
31
|
+
def after_task_step(self, task: Task) -> None:
|
|
32
|
+
assert task is _core.current_task()
|
|
33
|
+
self.record.append(("after", task))
|
|
34
|
+
|
|
35
|
+
def after_run(self) -> None:
|
|
36
|
+
self.record.append(("after_run", None))
|
|
37
|
+
|
|
38
|
+
def filter_tasks(self, tasks: Container[Task]) -> Iterable[tuple[str, Task | None]]:
|
|
39
|
+
for item in self.record:
|
|
40
|
+
if item[0] in ("schedule", "before", "after") and item[1] in tasks:
|
|
41
|
+
yield item
|
|
42
|
+
if item[0] in ("before_run", "after_run"):
|
|
43
|
+
yield item
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def test_instruments(recwarn: object) -> None:
|
|
47
|
+
r1 = TaskRecorder()
|
|
48
|
+
r2 = TaskRecorder()
|
|
49
|
+
r3 = TaskRecorder()
|
|
50
|
+
|
|
51
|
+
task = None
|
|
52
|
+
|
|
53
|
+
# We use a child task for this, because the main task does some extra
|
|
54
|
+
# bookkeeping stuff that can leak into the instrument results, and we
|
|
55
|
+
# don't want to deal with it.
|
|
56
|
+
async def task_fn() -> None:
|
|
57
|
+
nonlocal task
|
|
58
|
+
task = _core.current_task()
|
|
59
|
+
|
|
60
|
+
for _ in range(4):
|
|
61
|
+
await _core.checkpoint()
|
|
62
|
+
# replace r2 with r3, to test that we can manipulate them as we go
|
|
63
|
+
_core.remove_instrument(r2)
|
|
64
|
+
with pytest.raises(KeyError):
|
|
65
|
+
_core.remove_instrument(r2)
|
|
66
|
+
# add is idempotent
|
|
67
|
+
_core.add_instrument(r3)
|
|
68
|
+
_core.add_instrument(r3)
|
|
69
|
+
for _ in range(1):
|
|
70
|
+
await _core.checkpoint()
|
|
71
|
+
|
|
72
|
+
async def main() -> None:
|
|
73
|
+
async with _core.open_nursery() as nursery:
|
|
74
|
+
nursery.start_soon(task_fn)
|
|
75
|
+
|
|
76
|
+
_core.run(main, instruments=[r1, r2])
|
|
77
|
+
|
|
78
|
+
# It sleeps 5 times, so it runs 6 times. Note that checkpoint()
|
|
79
|
+
# reschedules the task immediately upon yielding, before the
|
|
80
|
+
# after_task_step event fires.
|
|
81
|
+
expected = (
|
|
82
|
+
[("before_run", None), ("schedule", task)]
|
|
83
|
+
+ [("before", task), ("schedule", task), ("after", task)] * 5
|
|
84
|
+
+ [("before", task), ("after", task), ("after_run", None)]
|
|
85
|
+
)
|
|
86
|
+
assert r1.record == r2.record + r3.record
|
|
87
|
+
assert task is not None
|
|
88
|
+
assert list(r1.filter_tasks([task])) == expected
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def test_instruments_interleave() -> None:
|
|
92
|
+
tasks = {}
|
|
93
|
+
|
|
94
|
+
async def two_step1() -> None:
|
|
95
|
+
tasks["t1"] = _core.current_task()
|
|
96
|
+
await _core.checkpoint()
|
|
97
|
+
|
|
98
|
+
async def two_step2() -> None:
|
|
99
|
+
tasks["t2"] = _core.current_task()
|
|
100
|
+
await _core.checkpoint()
|
|
101
|
+
|
|
102
|
+
async def main() -> None:
|
|
103
|
+
async with _core.open_nursery() as nursery:
|
|
104
|
+
nursery.start_soon(two_step1)
|
|
105
|
+
nursery.start_soon(two_step2)
|
|
106
|
+
|
|
107
|
+
r = TaskRecorder()
|
|
108
|
+
_core.run(main, instruments=[r])
|
|
109
|
+
|
|
110
|
+
expected = [
|
|
111
|
+
("before_run", None),
|
|
112
|
+
("schedule", tasks["t1"]),
|
|
113
|
+
("schedule", tasks["t2"]),
|
|
114
|
+
{
|
|
115
|
+
("before", tasks["t1"]),
|
|
116
|
+
("schedule", tasks["t1"]),
|
|
117
|
+
("after", tasks["t1"]),
|
|
118
|
+
("before", tasks["t2"]),
|
|
119
|
+
("schedule", tasks["t2"]),
|
|
120
|
+
("after", tasks["t2"]),
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
("before", tasks["t1"]),
|
|
124
|
+
("after", tasks["t1"]),
|
|
125
|
+
("before", tasks["t2"]),
|
|
126
|
+
("after", tasks["t2"]),
|
|
127
|
+
},
|
|
128
|
+
("after_run", None),
|
|
129
|
+
]
|
|
130
|
+
print(list(r.filter_tasks(tasks.values())))
|
|
131
|
+
check_sequence_matches(list(r.filter_tasks(tasks.values())), expected)
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
def test_null_instrument() -> None:
|
|
135
|
+
# undefined instrument methods are skipped
|
|
136
|
+
class NullInstrument(_abc.Instrument):
|
|
137
|
+
def something_unrelated(self) -> None:
|
|
138
|
+
pass # pragma: no cover
|
|
139
|
+
|
|
140
|
+
async def main() -> None:
|
|
141
|
+
await _core.checkpoint()
|
|
142
|
+
|
|
143
|
+
_core.run(main, instruments=[NullInstrument()])
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
def test_instrument_before_after_run() -> None:
|
|
147
|
+
record = []
|
|
148
|
+
|
|
149
|
+
class BeforeAfterRun(_abc.Instrument):
|
|
150
|
+
def before_run(self) -> None:
|
|
151
|
+
record.append("before_run")
|
|
152
|
+
|
|
153
|
+
def after_run(self) -> None:
|
|
154
|
+
record.append("after_run")
|
|
155
|
+
|
|
156
|
+
async def main() -> None:
|
|
157
|
+
pass
|
|
158
|
+
|
|
159
|
+
_core.run(main, instruments=[BeforeAfterRun()])
|
|
160
|
+
assert record == ["before_run", "after_run"]
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
def test_instrument_task_spawn_exit() -> None:
|
|
164
|
+
record = []
|
|
165
|
+
|
|
166
|
+
class SpawnExitRecorder(_abc.Instrument):
|
|
167
|
+
def task_spawned(self, task: Task) -> None:
|
|
168
|
+
record.append(("spawned", task))
|
|
169
|
+
|
|
170
|
+
def task_exited(self, task: Task) -> None:
|
|
171
|
+
record.append(("exited", task))
|
|
172
|
+
|
|
173
|
+
async def main() -> Task:
|
|
174
|
+
return _core.current_task()
|
|
175
|
+
|
|
176
|
+
main_task = _core.run(main, instruments=[SpawnExitRecorder()])
|
|
177
|
+
assert ("spawned", main_task) in record
|
|
178
|
+
assert ("exited", main_task) in record
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
# This test also tests having a crash before the initial task is even spawned,
|
|
182
|
+
# which is very difficult to handle.
|
|
183
|
+
def test_instruments_crash(caplog: pytest.LogCaptureFixture) -> None:
|
|
184
|
+
record = []
|
|
185
|
+
|
|
186
|
+
class BrokenInstrument(_abc.Instrument):
|
|
187
|
+
def task_scheduled(self, task: Task) -> NoReturn:
|
|
188
|
+
record.append("scheduled")
|
|
189
|
+
raise ValueError("oops")
|
|
190
|
+
|
|
191
|
+
def close(self) -> None:
|
|
192
|
+
# Shouldn't be called -- tests that the instrument disabling logic
|
|
193
|
+
# works right.
|
|
194
|
+
record.append("closed") # pragma: no cover
|
|
195
|
+
|
|
196
|
+
async def main() -> Task:
|
|
197
|
+
record.append("main ran")
|
|
198
|
+
return _core.current_task()
|
|
199
|
+
|
|
200
|
+
r = TaskRecorder()
|
|
201
|
+
main_task = _core.run(main, instruments=[r, BrokenInstrument()])
|
|
202
|
+
assert record == ["scheduled", "main ran"]
|
|
203
|
+
# the TaskRecorder kept going throughout, even though the BrokenInstrument
|
|
204
|
+
# was disabled
|
|
205
|
+
assert ("after", main_task) in r.record
|
|
206
|
+
assert ("after_run", None) in r.record
|
|
207
|
+
# And we got a log message
|
|
208
|
+
assert caplog.records[0].exc_info is not None
|
|
209
|
+
exc_type, exc_value, _exc_traceback = caplog.records[0].exc_info
|
|
210
|
+
assert exc_type is ValueError
|
|
211
|
+
assert str(exc_value) == "oops"
|
|
212
|
+
assert "Instrument has been disabled" in caplog.records[0].message
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
def test_instruments_monkeypatch() -> None:
|
|
216
|
+
class NullInstrument(_abc.Instrument):
|
|
217
|
+
pass
|
|
218
|
+
|
|
219
|
+
instrument = NullInstrument()
|
|
220
|
+
|
|
221
|
+
async def main() -> None:
|
|
222
|
+
record: list[Task] = []
|
|
223
|
+
|
|
224
|
+
# Changing the set of hooks implemented by an instrument after
|
|
225
|
+
# it's installed doesn't make them start being called right away
|
|
226
|
+
instrument.before_task_step = ( # type: ignore[method-assign]
|
|
227
|
+
record.append # type: ignore[assignment] # append is pos-only
|
|
228
|
+
)
|
|
229
|
+
|
|
230
|
+
await _core.checkpoint()
|
|
231
|
+
await _core.checkpoint()
|
|
232
|
+
assert len(record) == 0
|
|
233
|
+
|
|
234
|
+
# But if we remove and re-add the instrument, the new hooks are
|
|
235
|
+
# picked up
|
|
236
|
+
_core.remove_instrument(instrument)
|
|
237
|
+
_core.add_instrument(instrument)
|
|
238
|
+
await _core.checkpoint()
|
|
239
|
+
await _core.checkpoint()
|
|
240
|
+
assert record.count(_core.current_task()) == 2
|
|
241
|
+
|
|
242
|
+
_core.remove_instrument(instrument)
|
|
243
|
+
await _core.checkpoint()
|
|
244
|
+
await _core.checkpoint()
|
|
245
|
+
assert record.count(_core.current_task()) == 2
|
|
246
|
+
|
|
247
|
+
_core.run(main, instruments=[instrument])
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
def test_instrument_that_raises_on_getattr() -> None:
|
|
251
|
+
class EvilInstrument(_abc.Instrument):
|
|
252
|
+
def task_exited(self, task: Task) -> NoReturn:
|
|
253
|
+
raise AssertionError("this should never happen") # pragma: no cover
|
|
254
|
+
|
|
255
|
+
@property
|
|
256
|
+
def after_run(self) -> NoReturn:
|
|
257
|
+
raise ValueError("oops")
|
|
258
|
+
|
|
259
|
+
async def main() -> None:
|
|
260
|
+
with pytest.raises(ValueError, match=r"^oops$"):
|
|
261
|
+
_core.add_instrument(EvilInstrument())
|
|
262
|
+
|
|
263
|
+
# Make sure the instrument is fully removed from the per-method lists
|
|
264
|
+
runner = _core.current_task()._runner
|
|
265
|
+
assert "after_run" not in runner.instruments
|
|
266
|
+
assert "task_exited" not in runner.instruments
|
|
267
|
+
|
|
268
|
+
_core.run(main)
|
|
269
|
+
|
|
270
|
+
|
|
271
|
+
def test_instrument_call_trio_context() -> None:
|
|
272
|
+
called = set()
|
|
273
|
+
|
|
274
|
+
class Instrument(_abc.Instrument):
|
|
275
|
+
pass
|
|
276
|
+
|
|
277
|
+
hooks = {
|
|
278
|
+
# not run in task context
|
|
279
|
+
"after_io_wait": (True, False),
|
|
280
|
+
"before_io_wait": (True, False),
|
|
281
|
+
"before_run": (True, False),
|
|
282
|
+
"after_run": (True, False),
|
|
283
|
+
# run in task context
|
|
284
|
+
"before_task_step": (True, True),
|
|
285
|
+
"after_task_step": (True, True),
|
|
286
|
+
"task_exited": (True, True),
|
|
287
|
+
# depends
|
|
288
|
+
"task_scheduled": (True, None),
|
|
289
|
+
"task_spawned": (True, None),
|
|
290
|
+
}
|
|
291
|
+
for hook, val in hooks.items():
|
|
292
|
+
|
|
293
|
+
def h(
|
|
294
|
+
self: Instrument,
|
|
295
|
+
*args: object,
|
|
296
|
+
hook: str = hook,
|
|
297
|
+
val: tuple[bool, bool | None] = val,
|
|
298
|
+
) -> None:
|
|
299
|
+
fail_str = f"failed in {hook}"
|
|
300
|
+
|
|
301
|
+
assert _core.in_trio_run() == val[0], fail_str
|
|
302
|
+
if val[1] is not None:
|
|
303
|
+
assert _core.in_trio_task() == val[1], fail_str
|
|
304
|
+
called.add(hook)
|
|
305
|
+
|
|
306
|
+
setattr(Instrument, hook, h)
|
|
307
|
+
|
|
308
|
+
async def main() -> None:
|
|
309
|
+
await _core.checkpoint()
|
|
310
|
+
|
|
311
|
+
async with _core.open_nursery() as nursery:
|
|
312
|
+
nursery.start_soon(_core.checkpoint)
|
|
313
|
+
|
|
314
|
+
_core.run(main, instruments=[Instrument()])
|
|
315
|
+
assert called == set(hooks)
|