@ajksunkang-aios/kgraph-linux-x64 0.1.2 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (196) hide show
  1. package/bin/kgraph-launcher +15 -3
  2. package/lib/kgraph/scripts/build-bundle.sh +17 -4
  3. package/lib/site-packages/outcome/__init__.py +20 -0
  4. package/lib/site-packages/outcome/_impl.py +239 -0
  5. package/lib/site-packages/outcome/_util.py +33 -0
  6. package/lib/site-packages/outcome/_version.py +7 -0
  7. package/lib/site-packages/outcome/py.typed +0 -0
  8. package/lib/site-packages/outcome-1.3.0.post0.dist-info/INSTALLER +1 -0
  9. package/lib/site-packages/outcome-1.3.0.post0.dist-info/LICENSE +3 -0
  10. package/lib/site-packages/outcome-1.3.0.post0.dist-info/LICENSE.APACHE2 +202 -0
  11. package/lib/site-packages/outcome-1.3.0.post0.dist-info/LICENSE.MIT +20 -0
  12. package/lib/site-packages/outcome-1.3.0.post0.dist-info/METADATA +63 -0
  13. package/lib/site-packages/outcome-1.3.0.post0.dist-info/RECORD +13 -0
  14. package/lib/site-packages/outcome-1.3.0.post0.dist-info/WHEEL +6 -0
  15. package/lib/site-packages/outcome-1.3.0.post0.dist-info/top_level.txt +1 -0
  16. package/lib/site-packages/sniffio/__init__.py +17 -0
  17. package/lib/site-packages/sniffio/_impl.py +95 -0
  18. package/lib/site-packages/sniffio/_tests/__init__.py +0 -0
  19. package/lib/site-packages/sniffio/_tests/test_sniffio.py +84 -0
  20. package/lib/site-packages/sniffio/_version.py +3 -0
  21. package/lib/site-packages/sniffio/py.typed +0 -0
  22. package/lib/site-packages/sniffio-1.3.1.dist-info/INSTALLER +1 -0
  23. package/lib/site-packages/sniffio-1.3.1.dist-info/LICENSE +3 -0
  24. package/lib/site-packages/sniffio-1.3.1.dist-info/LICENSE.APACHE2 +202 -0
  25. package/lib/site-packages/sniffio-1.3.1.dist-info/LICENSE.MIT +20 -0
  26. package/lib/site-packages/sniffio-1.3.1.dist-info/METADATA +104 -0
  27. package/lib/site-packages/sniffio-1.3.1.dist-info/RECORD +14 -0
  28. package/lib/site-packages/sniffio-1.3.1.dist-info/WHEEL +5 -0
  29. package/lib/site-packages/sniffio-1.3.1.dist-info/top_level.txt +1 -0
  30. package/lib/site-packages/sortedcontainers/__init__.py +74 -0
  31. package/lib/site-packages/sortedcontainers/sorteddict.py +812 -0
  32. package/lib/site-packages/sortedcontainers/sortedlist.py +2646 -0
  33. package/lib/site-packages/sortedcontainers/sortedset.py +733 -0
  34. package/lib/site-packages/sortedcontainers-2.4.0.dist-info/INSTALLER +1 -0
  35. package/lib/site-packages/sortedcontainers-2.4.0.dist-info/LICENSE +13 -0
  36. package/lib/site-packages/sortedcontainers-2.4.0.dist-info/METADATA +264 -0
  37. package/lib/site-packages/sortedcontainers-2.4.0.dist-info/RECORD +10 -0
  38. package/lib/site-packages/sortedcontainers-2.4.0.dist-info/WHEEL +6 -0
  39. package/lib/site-packages/sortedcontainers-2.4.0.dist-info/top_level.txt +1 -0
  40. package/lib/site-packages/trio/__init__.py +133 -0
  41. package/lib/site-packages/trio/__main__.py +3 -0
  42. package/lib/site-packages/trio/_abc.py +714 -0
  43. package/lib/site-packages/trio/_channel.py +610 -0
  44. package/lib/site-packages/trio/_core/__init__.py +94 -0
  45. package/lib/site-packages/trio/_core/_asyncgens.py +243 -0
  46. package/lib/site-packages/trio/_core/_concat_tb.py +26 -0
  47. package/lib/site-packages/trio/_core/_entry_queue.py +223 -0
  48. package/lib/site-packages/trio/_core/_exceptions.py +169 -0
  49. package/lib/site-packages/trio/_core/_generated_instrumentation.py +50 -0
  50. package/lib/site-packages/trio/_core/_generated_io_epoll.py +98 -0
  51. package/lib/site-packages/trio/_core/_generated_io_kqueue.py +153 -0
  52. package/lib/site-packages/trio/_core/_generated_io_windows.py +204 -0
  53. package/lib/site-packages/trio/_core/_generated_run.py +269 -0
  54. package/lib/site-packages/trio/_core/_generated_windows_ffi.py +10 -0
  55. package/lib/site-packages/trio/_core/_instrumentation.py +117 -0
  56. package/lib/site-packages/trio/_core/_io_common.py +31 -0
  57. package/lib/site-packages/trio/_core/_io_epoll.py +385 -0
  58. package/lib/site-packages/trio/_core/_io_kqueue.py +292 -0
  59. package/lib/site-packages/trio/_core/_io_windows.py +1036 -0
  60. package/lib/site-packages/trio/_core/_ki.py +271 -0
  61. package/lib/site-packages/trio/_core/_local.py +104 -0
  62. package/lib/site-packages/trio/_core/_mock_clock.py +165 -0
  63. package/lib/site-packages/trio/_core/_parking_lot.py +317 -0
  64. package/lib/site-packages/trio/_core/_run.py +3148 -0
  65. package/lib/site-packages/trio/_core/_run_context.py +15 -0
  66. package/lib/site-packages/trio/_core/_tests/__init__.py +0 -0
  67. package/lib/site-packages/trio/_core/_tests/test_asyncgen.py +339 -0
  68. package/lib/site-packages/trio/_core/_tests/test_cancelled.py +222 -0
  69. package/lib/site-packages/trio/_core/_tests/test_exceptiongroup_gc.py +103 -0
  70. package/lib/site-packages/trio/_core/_tests/test_guest_mode.py +755 -0
  71. package/lib/site-packages/trio/_core/_tests/test_instrumentation.py +315 -0
  72. package/lib/site-packages/trio/_core/_tests/test_io.py +522 -0
  73. package/lib/site-packages/trio/_core/_tests/test_ki.py +703 -0
  74. package/lib/site-packages/trio/_core/_tests/test_local.py +118 -0
  75. package/lib/site-packages/trio/_core/_tests/test_mock_clock.py +193 -0
  76. package/lib/site-packages/trio/_core/_tests/test_parking_lot.py +389 -0
  77. package/lib/site-packages/trio/_core/_tests/test_run.py +3024 -0
  78. package/lib/site-packages/trio/_core/_tests/test_thread_cache.py +227 -0
  79. package/lib/site-packages/trio/_core/_tests/test_tutil.py +13 -0
  80. package/lib/site-packages/trio/_core/_tests/test_unbounded_queue.py +154 -0
  81. package/lib/site-packages/trio/_core/_tests/test_windows.py +305 -0
  82. package/lib/site-packages/trio/_core/_tests/tutil.py +117 -0
  83. package/lib/site-packages/trio/_core/_tests/type_tests/nursery_start.py +79 -0
  84. package/lib/site-packages/trio/_core/_tests/type_tests/run.py +51 -0
  85. package/lib/site-packages/trio/_core/_thread_cache.py +317 -0
  86. package/lib/site-packages/trio/_core/_traps.py +318 -0
  87. package/lib/site-packages/trio/_core/_unbounded_queue.py +163 -0
  88. package/lib/site-packages/trio/_core/_wakeup_socketpair.py +75 -0
  89. package/lib/site-packages/trio/_core/_windows_cffi.py +313 -0
  90. package/lib/site-packages/trio/_deprecate.py +171 -0
  91. package/lib/site-packages/trio/_dtls.py +1380 -0
  92. package/lib/site-packages/trio/_file_io.py +513 -0
  93. package/lib/site-packages/trio/_highlevel_generic.py +125 -0
  94. package/lib/site-packages/trio/_highlevel_open_tcp_listeners.py +251 -0
  95. package/lib/site-packages/trio/_highlevel_open_tcp_stream.py +397 -0
  96. package/lib/site-packages/trio/_highlevel_open_unix_stream.py +65 -0
  97. package/lib/site-packages/trio/_highlevel_serve_listeners.py +148 -0
  98. package/lib/site-packages/trio/_highlevel_socket.py +423 -0
  99. package/lib/site-packages/trio/_highlevel_ssl_helpers.py +180 -0
  100. package/lib/site-packages/trio/_path.py +289 -0
  101. package/lib/site-packages/trio/_repl.py +159 -0
  102. package/lib/site-packages/trio/_signals.py +185 -0
  103. package/lib/site-packages/trio/_socket.py +1326 -0
  104. package/lib/site-packages/trio/_ssl.py +964 -0
  105. package/lib/site-packages/trio/_subprocess.py +1178 -0
  106. package/lib/site-packages/trio/_subprocess_platform/__init__.py +123 -0
  107. package/lib/site-packages/trio/_subprocess_platform/kqueue.py +48 -0
  108. package/lib/site-packages/trio/_subprocess_platform/waitid.py +113 -0
  109. package/lib/site-packages/trio/_subprocess_platform/windows.py +11 -0
  110. package/lib/site-packages/trio/_sync.py +908 -0
  111. package/lib/site-packages/trio/_tests/__init__.py +0 -0
  112. package/lib/site-packages/trio/_tests/astrill-codesigning-cert.cer +0 -0
  113. package/lib/site-packages/trio/_tests/check_type_completeness.py +247 -0
  114. package/lib/site-packages/trio/_tests/module_with_deprecations.py +22 -0
  115. package/lib/site-packages/trio/_tests/pytest_plugin.py +54 -0
  116. package/lib/site-packages/trio/_tests/test_abc.py +72 -0
  117. package/lib/site-packages/trio/_tests/test_channel.py +750 -0
  118. package/lib/site-packages/trio/_tests/test_contextvars.py +56 -0
  119. package/lib/site-packages/trio/_tests/test_deprecate.py +277 -0
  120. package/lib/site-packages/trio/_tests/test_deprecate_strict_exception_groups_false.py +64 -0
  121. package/lib/site-packages/trio/_tests/test_dtls.py +950 -0
  122. package/lib/site-packages/trio/_tests/test_exports.py +626 -0
  123. package/lib/site-packages/trio/_tests/test_fakenet.py +317 -0
  124. package/lib/site-packages/trio/_tests/test_file_io.py +269 -0
  125. package/lib/site-packages/trio/_tests/test_highlevel_generic.py +98 -0
  126. package/lib/site-packages/trio/_tests/test_highlevel_open_tcp_listeners.py +419 -0
  127. package/lib/site-packages/trio/_tests/test_highlevel_open_tcp_stream.py +693 -0
  128. package/lib/site-packages/trio/_tests/test_highlevel_open_unix_stream.py +86 -0
  129. package/lib/site-packages/trio/_tests/test_highlevel_serve_listeners.py +186 -0
  130. package/lib/site-packages/trio/_tests/test_highlevel_socket.py +336 -0
  131. package/lib/site-packages/trio/_tests/test_highlevel_ssl_helpers.py +169 -0
  132. package/lib/site-packages/trio/_tests/test_path.py +279 -0
  133. package/lib/site-packages/trio/_tests/test_repl.py +428 -0
  134. package/lib/site-packages/trio/_tests/test_scheduler_determinism.py +47 -0
  135. package/lib/site-packages/trio/_tests/test_signals.py +186 -0
  136. package/lib/site-packages/trio/_tests/test_socket.py +1253 -0
  137. package/lib/site-packages/trio/_tests/test_ssl.py +1371 -0
  138. package/lib/site-packages/trio/_tests/test_subprocess.py +767 -0
  139. package/lib/site-packages/trio/_tests/test_sync.py +735 -0
  140. package/lib/site-packages/trio/_tests/test_testing.py +682 -0
  141. package/lib/site-packages/trio/_tests/test_testing_raisesgroup.py +1128 -0
  142. package/lib/site-packages/trio/_tests/test_threads.py +1173 -0
  143. package/lib/site-packages/trio/_tests/test_timeouts.py +281 -0
  144. package/lib/site-packages/trio/_tests/test_tracing.py +88 -0
  145. package/lib/site-packages/trio/_tests/test_trio.py +8 -0
  146. package/lib/site-packages/trio/_tests/test_unix_pipes.py +288 -0
  147. package/lib/site-packages/trio/_tests/test_util.py +349 -0
  148. package/lib/site-packages/trio/_tests/test_wait_for_object.py +225 -0
  149. package/lib/site-packages/trio/_tests/test_windows_pipes.py +112 -0
  150. package/lib/site-packages/trio/_tests/tools/__init__.py +0 -0
  151. package/lib/site-packages/trio/_tests/tools/test_gen_exports.py +179 -0
  152. package/lib/site-packages/trio/_tests/tools/test_mypy_annotate.py +140 -0
  153. package/lib/site-packages/trio/_tests/tools/test_sync_requirements.py +80 -0
  154. package/lib/site-packages/trio/_tests/type_tests/check_wraps.py +9 -0
  155. package/lib/site-packages/trio/_tests/type_tests/open_memory_channel.py +4 -0
  156. package/lib/site-packages/trio/_tests/type_tests/path.py +140 -0
  157. package/lib/site-packages/trio/_tests/type_tests/subprocesses.py +23 -0
  158. package/lib/site-packages/trio/_tests/type_tests/task_status.py +29 -0
  159. package/lib/site-packages/trio/_threads.py +610 -0
  160. package/lib/site-packages/trio/_timeouts.py +197 -0
  161. package/lib/site-packages/trio/_tools/__init__.py +0 -0
  162. package/lib/site-packages/trio/_tools/gen_exports.py +401 -0
  163. package/lib/site-packages/trio/_tools/mypy_annotate.py +126 -0
  164. package/lib/site-packages/trio/_tools/sync_requirements.py +98 -0
  165. package/lib/site-packages/trio/_tools/windows_ffi_build.py +220 -0
  166. package/lib/site-packages/trio/_unix_pipes.py +197 -0
  167. package/lib/site-packages/trio/_util.py +385 -0
  168. package/lib/site-packages/trio/_version.py +3 -0
  169. package/lib/site-packages/trio/_wait_for_object.py +67 -0
  170. package/lib/site-packages/trio/_windows_pipes.py +144 -0
  171. package/lib/site-packages/trio/abc.py +23 -0
  172. package/lib/site-packages/trio/from_thread.py +13 -0
  173. package/lib/site-packages/trio/lowlevel.py +95 -0
  174. package/lib/site-packages/trio/py.typed +0 -0
  175. package/lib/site-packages/trio/socket.py +602 -0
  176. package/lib/site-packages/trio/testing/__init__.py +58 -0
  177. package/lib/site-packages/trio/testing/_check_streams.py +570 -0
  178. package/lib/site-packages/trio/testing/_checkpoints.py +69 -0
  179. package/lib/site-packages/trio/testing/_fake_net.py +584 -0
  180. package/lib/site-packages/trio/testing/_memory_streams.py +633 -0
  181. package/lib/site-packages/trio/testing/_network.py +36 -0
  182. package/lib/site-packages/trio/testing/_raises_group.py +1015 -0
  183. package/lib/site-packages/trio/testing/_sequencer.py +87 -0
  184. package/lib/site-packages/trio/testing/_trio_test.py +50 -0
  185. package/lib/site-packages/trio/to_thread.py +4 -0
  186. package/lib/site-packages/trio-0.33.0.dist-info/INSTALLER +1 -0
  187. package/lib/site-packages/trio-0.33.0.dist-info/METADATA +186 -0
  188. package/lib/site-packages/trio-0.33.0.dist-info/RECORD +156 -0
  189. package/lib/site-packages/trio-0.33.0.dist-info/REQUESTED +0 -0
  190. package/lib/site-packages/trio-0.33.0.dist-info/WHEEL +5 -0
  191. package/lib/site-packages/trio-0.33.0.dist-info/entry_points.txt +2 -0
  192. package/lib/site-packages/trio-0.33.0.dist-info/licenses/LICENSE +3 -0
  193. package/lib/site-packages/trio-0.33.0.dist-info/licenses/LICENSE.APACHE2 +202 -0
  194. package/lib/site-packages/trio-0.33.0.dist-info/licenses/LICENSE.MIT +22 -0
  195. package/lib/site-packages/trio-0.33.0.dist-info/top_level.txt +1 -0
  196. package/package.json +1 -1
@@ -0,0 +1,281 @@
1
+ from __future__ import annotations
2
+
3
+ import time
4
+ from typing import TYPE_CHECKING, Protocol, TypeVar
5
+
6
+ import outcome
7
+ import pytest
8
+
9
+ import trio
10
+
11
+ from .. import _core
12
+ from .._core._tests.tutil import slow
13
+ from .._timeouts import (
14
+ TooSlowError,
15
+ fail_after,
16
+ fail_at,
17
+ move_on_after,
18
+ move_on_at,
19
+ sleep,
20
+ sleep_forever,
21
+ sleep_until,
22
+ )
23
+ from ..testing import assert_checkpoints
24
+
25
+ if TYPE_CHECKING:
26
+ from collections.abc import Awaitable, Callable
27
+
28
+ T = TypeVar("T")
29
+
30
+
31
+ async def check_takes_about(f: Callable[[], Awaitable[T]], expected_dur: float) -> T:
32
+ start = time.perf_counter()
33
+ result = await outcome.acapture(f)
34
+ dur = time.perf_counter() - start
35
+ print(dur / expected_dur)
36
+ # 1.5 is an arbitrary fudge factor because there's always some delay
37
+ # between when we become eligible to wake up and when we actually do. We
38
+ # used to sleep for 0.05, and regularly observed overruns of 1.6x on
39
+ # Appveyor, and then started seeing overruns of 2.3x on Travis's macOS, so
40
+ # now we bumped up the sleep to 1 second, marked the tests as slow, and
41
+ # hopefully now the proportional error will be less huge.
42
+ #
43
+ # We also also for durations that are a hair shorter than expected. For
44
+ # example, here's a run on Windows where a 1.0 second sleep was measured
45
+ # to take 0.9999999999999858 seconds:
46
+ # https://ci.appveyor.com/project/njsmith/trio/build/1.0.768/job/3lbdyxl63q3h9s21
47
+ # I believe that what happened here is that Windows's low clock resolution
48
+ # meant that our calls to time.monotonic() returned exactly the same
49
+ # values as the calls inside the actual run loop, but the two subtractions
50
+ # returned slightly different values because the run loop's clock adds a
51
+ # random floating point offset to both times, which should cancel out, but
52
+ # lol floating point we got slightly different rounding errors. (That
53
+ # value above is exactly 128 ULPs below 1.0, which would make sense if it
54
+ # started as a 1 ULP error at a different dynamic range.)
55
+ assert (1 - 1e-8) <= (dur / expected_dur) < 1.5
56
+
57
+ return result.unwrap()
58
+
59
+
60
+ # How long to (attempt to) sleep for when testing. Smaller numbers make the
61
+ # test suite go faster.
62
+ TARGET = 1.0
63
+
64
+
65
+ @slow
66
+ async def test_sleep() -> None:
67
+ async def sleep_1() -> None:
68
+ await sleep_until(_core.current_time() + TARGET)
69
+
70
+ await check_takes_about(sleep_1, TARGET)
71
+
72
+ async def sleep_2() -> None:
73
+ await sleep(TARGET)
74
+
75
+ await check_takes_about(sleep_2, TARGET)
76
+
77
+ with assert_checkpoints():
78
+ await sleep(0)
79
+ # This also serves as a test of the trivial move_on_at
80
+ with move_on_at(_core.current_time()):
81
+ with pytest.raises(_core.Cancelled):
82
+ await sleep(0)
83
+
84
+
85
+ @slow
86
+ async def test_move_on_after() -> None:
87
+ async def sleep_3() -> None:
88
+ with move_on_after(TARGET):
89
+ await sleep(100)
90
+
91
+ await check_takes_about(sleep_3, TARGET)
92
+
93
+
94
+ async def test_cannot_wake_sleep_forever() -> None:
95
+ # Test an error occurs if you manually wake sleep_forever().
96
+ task = trio.lowlevel.current_task()
97
+
98
+ async def wake_task() -> None:
99
+ await trio.lowlevel.checkpoint()
100
+ trio.lowlevel.reschedule(task, outcome.Value(None))
101
+
102
+ async with trio.open_nursery() as nursery:
103
+ nursery.start_soon(wake_task)
104
+ with pytest.raises(RuntimeError):
105
+ await trio.sleep_forever()
106
+
107
+
108
+ class TimeoutScope(Protocol):
109
+ def __call__(self, seconds: float, *, shield: bool) -> trio.CancelScope: ...
110
+
111
+
112
+ @pytest.mark.parametrize("scope", [move_on_after, fail_after])
113
+ async def test_context_shields_from_outer(scope: TimeoutScope) -> None:
114
+ with _core.CancelScope() as outer, scope(TARGET, shield=True) as inner:
115
+ outer.cancel()
116
+ try:
117
+ await trio.lowlevel.checkpoint()
118
+ except trio.Cancelled: # pragma: no cover
119
+ pytest.fail("shield didn't work")
120
+ inner.shield = False
121
+ with pytest.raises(trio.Cancelled):
122
+ await trio.lowlevel.checkpoint()
123
+
124
+
125
+ @slow
126
+ async def test_move_on_after_moves_on_even_if_shielded() -> None:
127
+ async def task() -> None:
128
+ with _core.CancelScope() as outer, move_on_after(TARGET, shield=True):
129
+ outer.cancel()
130
+ # The outer scope is cancelled, but this task is protected by the
131
+ # shield, so it manages to get to sleep until deadline is met
132
+ await sleep_forever()
133
+
134
+ await check_takes_about(task, TARGET)
135
+
136
+
137
+ @slow
138
+ async def test_fail_after_fails_even_if_shielded() -> None:
139
+ async def task() -> None:
140
+ with (
141
+ pytest.raises(TooSlowError),
142
+ _core.CancelScope() as outer,
143
+ fail_after(
144
+ TARGET,
145
+ shield=True,
146
+ ),
147
+ ):
148
+ outer.cancel()
149
+ # The outer scope is cancelled, but this task is protected by the
150
+ # shield, so it manages to get to sleep until deadline is met
151
+ await sleep_forever()
152
+
153
+ await check_takes_about(task, TARGET)
154
+
155
+
156
+ @slow
157
+ async def test_fail() -> None:
158
+ async def sleep_4() -> None:
159
+ with fail_at(_core.current_time() + TARGET):
160
+ await sleep(100)
161
+
162
+ with pytest.raises(TooSlowError):
163
+ await check_takes_about(sleep_4, TARGET)
164
+
165
+ with fail_at(_core.current_time() + 100):
166
+ await sleep(0)
167
+
168
+ async def sleep_5() -> None:
169
+ with fail_after(TARGET):
170
+ await sleep(100)
171
+
172
+ with pytest.raises(TooSlowError):
173
+ await check_takes_about(sleep_5, TARGET)
174
+
175
+ with fail_after(100):
176
+ await sleep(0)
177
+
178
+
179
+ async def test_timeouts_raise_value_error() -> None:
180
+ # deadlines are allowed to be negative, but not delays.
181
+ # neither delays nor deadlines are allowed to be NaN
182
+
183
+ nan = float("nan")
184
+
185
+ for fun, val in (
186
+ (sleep, -1),
187
+ (sleep, nan),
188
+ (sleep_until, nan),
189
+ ):
190
+ with pytest.raises(
191
+ ValueError,
192
+ match=r"^(deadline|`seconds`) must (not )*be (non-negative|NaN)$",
193
+ ):
194
+ await fun(val)
195
+
196
+ for cm, val in (
197
+ (fail_after, -1),
198
+ (fail_after, nan),
199
+ (fail_at, nan),
200
+ (move_on_after, -1),
201
+ (move_on_after, nan),
202
+ (move_on_at, nan),
203
+ ):
204
+ with pytest.raises(
205
+ ValueError,
206
+ match=r"^(deadline|`seconds`) must (not )*be (non-negative|NaN)$",
207
+ ):
208
+ with cm(val):
209
+ pass # pragma: no cover
210
+
211
+
212
+ async def test_timeout_deadline_on_entry(mock_clock: _core.MockClock) -> None:
213
+ rcs = move_on_after(5)
214
+ assert rcs.relative_deadline == 5
215
+
216
+ mock_clock.jump(3)
217
+ start = _core.current_time()
218
+ with rcs as cs:
219
+ assert cs.is_relative is None
220
+
221
+ # This would previously be start+2
222
+ assert cs.deadline == start + 5
223
+ assert cs.relative_deadline == 5
224
+
225
+ cs.deadline = start + 3
226
+ assert cs.deadline == start + 3
227
+ assert cs.relative_deadline == 3
228
+
229
+ cs.relative_deadline = 4
230
+ assert cs.deadline == start + 4
231
+ assert cs.relative_deadline == 4
232
+
233
+ rcs = move_on_after(5)
234
+ assert rcs.shield is False
235
+ rcs.shield = True
236
+ assert rcs.shield is True
237
+
238
+ mock_clock.jump(3)
239
+ start = _core.current_time()
240
+ with rcs as cs:
241
+ assert cs.deadline == start + 5
242
+
243
+ assert rcs is cs
244
+
245
+
246
+ async def test_invalid_access_unentered(mock_clock: _core.MockClock) -> None:
247
+ cs = move_on_after(5)
248
+ mock_clock.jump(3)
249
+ start = _core.current_time()
250
+
251
+ match_str = "^unentered relative cancel scope does not have an absolute deadline"
252
+ with pytest.warns(DeprecationWarning, match=match_str):
253
+ assert cs.deadline == start + 5
254
+ mock_clock.jump(1)
255
+ # this is hella sketchy, but they *have* been warned
256
+ with pytest.warns(DeprecationWarning, match=match_str):
257
+ assert cs.deadline == start + 6
258
+
259
+ with pytest.warns(DeprecationWarning, match=match_str):
260
+ cs.deadline = 7
261
+ # now transformed into absolute
262
+ assert cs.deadline == 7
263
+ assert not cs.is_relative
264
+
265
+ cs = move_on_at(5)
266
+
267
+ match_str = (
268
+ "^unentered non-relative cancel scope does not have a relative deadline$"
269
+ )
270
+ with pytest.raises(RuntimeError, match=match_str):
271
+ assert cs.relative_deadline
272
+ with pytest.raises(RuntimeError, match=match_str):
273
+ cs.relative_deadline = 7
274
+
275
+
276
+ @pytest.mark.xfail(reason="not implemented")
277
+ async def test_fail_access_before_entering() -> None: # pragma: no cover
278
+ my_fail_at = fail_at(5)
279
+ assert my_fail_at.deadline # type: ignore[attr-defined]
280
+ my_fail_after = fail_after(5)
281
+ assert my_fail_after.relative_deadline # type: ignore[attr-defined]
@@ -0,0 +1,88 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import TYPE_CHECKING
4
+
5
+ import trio
6
+
7
+ if TYPE_CHECKING:
8
+ from collections.abc import AsyncGenerator
9
+
10
+
11
+ async def coro1(event: trio.Event) -> None:
12
+ event.set()
13
+ await trio.sleep_forever()
14
+
15
+
16
+ async def coro2(event: trio.Event) -> None:
17
+ await coro1(event)
18
+
19
+
20
+ async def coro3(event: trio.Event) -> None:
21
+ await coro2(event)
22
+
23
+
24
+ async def coro2_async_gen(event: trio.Event) -> AsyncGenerator[None, None]:
25
+ # mypy does not like `yield await trio.lowlevel.checkpoint()` - but that
26
+ # should be equivalent to splitting the statement
27
+ await trio.lowlevel.checkpoint()
28
+ yield
29
+ await coro1(event)
30
+ yield # pragma: no cover
31
+ await trio.lowlevel.checkpoint() # pragma: no cover
32
+ yield # pragma: no cover
33
+
34
+
35
+ async def coro3_async_gen(event: trio.Event) -> None:
36
+ async for _ in coro2_async_gen(event):
37
+ pass
38
+
39
+
40
+ async def test_task_iter_await_frames() -> None:
41
+ async with trio.open_nursery() as nursery:
42
+ event = trio.Event()
43
+ nursery.start_soon(coro3, event)
44
+ await event.wait()
45
+
46
+ (task,) = nursery.child_tasks
47
+
48
+ assert [frame.f_code.co_name for frame, _ in task.iter_await_frames()][:3] == [
49
+ "coro3",
50
+ "coro2",
51
+ "coro1",
52
+ ]
53
+
54
+ nursery.cancel_scope.cancel()
55
+
56
+
57
+ async def test_task_iter_await_frames_async_gen() -> None:
58
+ async with trio.open_nursery() as nursery:
59
+ event = trio.Event()
60
+ nursery.start_soon(coro3_async_gen, event)
61
+ await event.wait()
62
+
63
+ (task,) = nursery.child_tasks
64
+
65
+ assert [frame.f_code.co_name for frame, _ in task.iter_await_frames()][:3] == [
66
+ "coro3_async_gen",
67
+ "coro2_async_gen",
68
+ "coro1",
69
+ ]
70
+
71
+ nursery.cancel_scope.cancel()
72
+
73
+
74
+ async def test_closed_task_iter_await_frames() -> None:
75
+ async with trio.open_nursery() as nursery:
76
+ task = object()
77
+
78
+ async def capture_task() -> None:
79
+ nonlocal task
80
+ task = trio.lowlevel.current_task()
81
+ await trio.lowlevel.checkpoint()
82
+
83
+ nursery.start_soon(capture_task)
84
+
85
+ # Task has completed, so coro.cr_frame should be None, thus no frames
86
+ assert isinstance(task, trio.lowlevel.Task) # Ran `capture_task`
87
+ assert task.coro.cr_frame is None # and the task was over, but
88
+ assert list(task.iter_await_frames()) == [] # look, no crash!
@@ -0,0 +1,8 @@
1
+ def test_trio_import() -> None:
2
+ import sys
3
+
4
+ for module in list(sys.modules.keys()):
5
+ if module.startswith("trio"):
6
+ del sys.modules[module]
7
+
8
+ import trio # noqa: F401
@@ -0,0 +1,288 @@
1
+ from __future__ import annotations
2
+
3
+ import errno
4
+ import os
5
+ import select
6
+ import sys
7
+ from typing import TYPE_CHECKING
8
+
9
+ import pytest
10
+
11
+ from .. import _core
12
+ from .._core._tests.tutil import gc_collect_harder, skip_if_fbsd_pipes_broken
13
+ from ..testing import check_one_way_stream, wait_all_tasks_blocked
14
+
15
+ if TYPE_CHECKING:
16
+ from .._file_io import _HasFileNo
17
+
18
+ posix = os.name == "posix"
19
+ pytestmark = pytest.mark.skipif(not posix, reason="posix only")
20
+
21
+ assert not TYPE_CHECKING or sys.platform == "unix"
22
+
23
+ if posix:
24
+ from .._unix_pipes import FdStream
25
+
26
+
27
+ async def make_pipe() -> tuple[FdStream, FdStream]:
28
+ """Makes a new pair of pipes."""
29
+ r, w = os.pipe()
30
+ return FdStream(w), FdStream(r)
31
+
32
+
33
+ async def make_clogged_pipe() -> tuple[FdStream, FdStream]:
34
+ s, r = await make_pipe()
35
+ try:
36
+ while True:
37
+ # We want to totally fill up the pipe buffer.
38
+ # This requires working around a weird feature that POSIX pipes
39
+ # have.
40
+ # If you do a write of <= PIPE_BUF bytes, then it's guaranteed
41
+ # to either complete entirely, or not at all. So if we tried to
42
+ # write PIPE_BUF bytes, and the buffer's free space is only
43
+ # PIPE_BUF/2, then the write will raise BlockingIOError... even
44
+ # though a smaller write could still succeed! To avoid this,
45
+ # make sure to write >PIPE_BUF bytes each time, which disables
46
+ # the special behavior.
47
+ # For details, search for PIPE_BUF here:
48
+ # http://pubs.opengroup.org/onlinepubs/9699919799/functions/write.html
49
+
50
+ # for the getattr:
51
+ # https://bitbucket.org/pypy/pypy/issues/2876/selectpipe_buf-is-missing-on-pypy3
52
+ buf_size = getattr(select, "PIPE_BUF", 8192)
53
+ os.write(s.fileno(), b"x" * buf_size * 2)
54
+ except BlockingIOError:
55
+ pass
56
+ return s, r
57
+
58
+
59
+ async def test_send_pipe() -> None:
60
+ r, w = os.pipe()
61
+ async with FdStream(w) as send:
62
+ assert send.fileno() == w
63
+ await send.send_all(b"123")
64
+ assert (os.read(r, 8)) == b"123"
65
+
66
+ os.close(r)
67
+
68
+
69
+ async def test_receive_pipe() -> None:
70
+ r, w = os.pipe()
71
+ async with FdStream(r) as recv:
72
+ assert (recv.fileno()) == r
73
+ os.write(w, b"123")
74
+ assert (await recv.receive_some(8)) == b"123"
75
+
76
+ os.close(w)
77
+
78
+
79
+ async def test_pipes_combined() -> None:
80
+ write, read = await make_pipe()
81
+ count = 2**20
82
+
83
+ async def sender() -> None:
84
+ big = bytearray(count)
85
+ await write.send_all(big)
86
+
87
+ async def reader() -> None:
88
+ await wait_all_tasks_blocked()
89
+ received = 0
90
+ while received < count:
91
+ received += len(await read.receive_some(4096))
92
+
93
+ assert received == count
94
+
95
+ async with _core.open_nursery() as n:
96
+ n.start_soon(sender)
97
+ n.start_soon(reader)
98
+
99
+ await read.aclose()
100
+ await write.aclose()
101
+
102
+
103
+ async def test_pipe_errors() -> None:
104
+ with pytest.raises(TypeError):
105
+ FdStream(None)
106
+
107
+ r, w = os.pipe()
108
+ os.close(w)
109
+ async with FdStream(r) as s:
110
+ with pytest.raises(ValueError, match=r"^max_bytes must be integer >= 1$"):
111
+ await s.receive_some(0)
112
+
113
+
114
+ async def test_del() -> None:
115
+ w, r = await make_pipe()
116
+ f1, f2 = w.fileno(), r.fileno()
117
+ del w, r
118
+ gc_collect_harder()
119
+
120
+ with pytest.raises(OSError, match=r"Bad file descriptor$") as excinfo:
121
+ os.close(f1)
122
+ assert excinfo.value.errno == errno.EBADF
123
+
124
+ with pytest.raises(OSError, match=r"Bad file descriptor$") as excinfo:
125
+ os.close(f2)
126
+ assert excinfo.value.errno == errno.EBADF
127
+
128
+
129
+ async def test_async_with() -> None:
130
+ w, r = await make_pipe()
131
+ async with w, r:
132
+ pass
133
+
134
+ assert w.fileno() == -1
135
+ assert r.fileno() == -1
136
+
137
+ with pytest.raises(OSError, match=r"Bad file descriptor$") as excinfo:
138
+ os.close(w.fileno())
139
+ assert excinfo.value.errno == errno.EBADF
140
+
141
+ with pytest.raises(OSError, match=r"Bad file descriptor$") as excinfo:
142
+ os.close(r.fileno())
143
+ assert excinfo.value.errno == errno.EBADF
144
+
145
+
146
+ async def test_misdirected_aclose_regression() -> None:
147
+ # https://github.com/python-trio/trio/issues/661#issuecomment-456582356
148
+ w, r = await make_pipe()
149
+ old_r_fd = r.fileno()
150
+
151
+ # Close the original objects
152
+ await w.aclose()
153
+ await r.aclose()
154
+
155
+ # Do a little dance to get a new pipe whose receive handle matches the old
156
+ # receive handle.
157
+ r2_fd, w2_fd = os.pipe()
158
+ if r2_fd != old_r_fd: # pragma: no cover
159
+ os.dup2(r2_fd, old_r_fd)
160
+ os.close(r2_fd)
161
+ async with FdStream(old_r_fd) as r2:
162
+ assert r2.fileno() == old_r_fd
163
+
164
+ # And now set up a background task that's working on the new receive
165
+ # handle
166
+ async def expect_eof() -> None:
167
+ assert await r2.receive_some(10) == b""
168
+
169
+ async with _core.open_nursery() as nursery:
170
+ nursery.start_soon(expect_eof)
171
+ await wait_all_tasks_blocked()
172
+
173
+ # Here's the key test: does calling aclose() again on the *old*
174
+ # handle, cause the task blocked on the *new* handle to raise
175
+ # ClosedResourceError?
176
+ await r.aclose()
177
+ await wait_all_tasks_blocked()
178
+
179
+ # Guess we survived! Close the new write handle so that the task
180
+ # gets an EOF and can exit cleanly.
181
+ os.close(w2_fd)
182
+
183
+
184
+ async def test_close_at_bad_time_for_receive_some(
185
+ monkeypatch: pytest.MonkeyPatch,
186
+ ) -> None:
187
+ # We used to have race conditions where if one task was using the pipe,
188
+ # and another closed it at *just* the wrong moment, it would give an
189
+ # unexpected error instead of ClosedResourceError:
190
+ # https://github.com/python-trio/trio/issues/661
191
+ #
192
+ # This tests what happens if the pipe gets closed in the moment *between*
193
+ # when receive_some wakes up, and when it tries to call os.read
194
+ async def expect_closedresourceerror() -> None:
195
+ with pytest.raises(_core.ClosedResourceError):
196
+ await r.receive_some(10)
197
+
198
+ orig_wait_readable = _core._run.TheIOManager.wait_readable
199
+
200
+ async def patched_wait_readable(
201
+ self: _core._run.TheIOManager,
202
+ fd: int | _HasFileNo,
203
+ ) -> None:
204
+ await orig_wait_readable(self, fd)
205
+ await r.aclose()
206
+
207
+ monkeypatch.setattr(_core._run.TheIOManager, "wait_readable", patched_wait_readable)
208
+ s, r = await make_pipe()
209
+ async with s, r:
210
+ async with _core.open_nursery() as nursery:
211
+ nursery.start_soon(expect_closedresourceerror)
212
+ await wait_all_tasks_blocked()
213
+ # Trigger everything by waking up the receiver
214
+ await s.send_all(b"x")
215
+
216
+
217
+ async def test_close_at_bad_time_for_send_all(monkeypatch: pytest.MonkeyPatch) -> None:
218
+ # We used to have race conditions where if one task was using the pipe,
219
+ # and another closed it at *just* the wrong moment, it would give an
220
+ # unexpected error instead of ClosedResourceError:
221
+ # https://github.com/python-trio/trio/issues/661
222
+ #
223
+ # This tests what happens if the pipe gets closed in the moment *between*
224
+ # when send_all wakes up, and when it tries to call os.write
225
+ async def expect_closedresourceerror() -> None:
226
+ with pytest.raises(_core.ClosedResourceError):
227
+ await s.send_all(b"x" * 100)
228
+
229
+ orig_wait_writable = _core._run.TheIOManager.wait_writable
230
+
231
+ async def patched_wait_writable(
232
+ self: _core._run.TheIOManager,
233
+ fd: int | _HasFileNo,
234
+ ) -> None:
235
+ await orig_wait_writable(self, fd)
236
+ await s.aclose()
237
+
238
+ monkeypatch.setattr(_core._run.TheIOManager, "wait_writable", patched_wait_writable)
239
+ s, r = await make_clogged_pipe()
240
+ async with s, r:
241
+ async with _core.open_nursery() as nursery:
242
+ nursery.start_soon(expect_closedresourceerror)
243
+ await wait_all_tasks_blocked()
244
+ # Trigger everything by waking up the sender. On ppc64el, PIPE_BUF
245
+ # is 8192 but make_clogged_pipe() ends up writing a total of
246
+ # 1048576 bytes before the pipe is full, and then a subsequent
247
+ # receive_some(10000) isn't sufficient for orig_wait_writable() to
248
+ # return for our subsequent aclose() call. It's necessary to empty
249
+ # the pipe further before this happens. So we loop here until the
250
+ # pipe is empty to make sure that the sender wakes up even in this
251
+ # case. Otherwise patched_wait_writable() never gets to the
252
+ # aclose(), so expect_closedresourceerror() never returns, the
253
+ # nursery never finishes all tasks and this test hangs.
254
+ received_data = await r.receive_some(10000)
255
+ while received_data:
256
+ received_data = await r.receive_some(10000)
257
+
258
+
259
+ # On FreeBSD, directories are readable, and we haven't found any other trick
260
+ # for making an unreadable fd, so there's no way to run this test. Fortunately
261
+ # the logic this is testing doesn't depend on the platform, so testing on
262
+ # other platforms is probably good enough.
263
+ @pytest.mark.skipif(
264
+ sys.platform.startswith("freebsd"),
265
+ reason="no way to make read() return a bizarro error on FreeBSD",
266
+ )
267
+ async def test_bizarro_OSError_from_receive() -> None:
268
+ # Make sure that if the read syscall returns some bizarro error, then we
269
+ # get a BrokenResourceError. This is incredibly unlikely; there's almost
270
+ # no way to trigger a failure here intentionally (except for EBADF, but we
271
+ # exploit that to detect file closure, so it takes a different path). So
272
+ # we set up a strange scenario where the pipe fd somehow transmutes into a
273
+ # directory fd, causing os.read to raise IsADirectoryError (yes, that's a
274
+ # real built-in exception type).
275
+ s, r = await make_pipe()
276
+ async with s, r:
277
+ dir_fd = os.open("/", os.O_DIRECTORY, 0)
278
+ try:
279
+ os.dup2(dir_fd, r.fileno())
280
+ with pytest.raises(_core.BrokenResourceError):
281
+ await r.receive_some(10)
282
+ finally:
283
+ os.close(dir_fd)
284
+
285
+
286
+ @skip_if_fbsd_pipes_broken
287
+ async def test_pipe_fully() -> None:
288
+ await check_one_way_stream(make_pipe, make_clogged_pipe)