@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,750 @@
1
+ from __future__ import annotations
2
+
3
+ import sys
4
+ from typing import TYPE_CHECKING
5
+
6
+ import pytest
7
+
8
+ import trio
9
+ from trio import EndOfChannel, as_safe_channel, open_memory_channel
10
+
11
+ from ..testing import assert_checkpoints, wait_all_tasks_blocked
12
+
13
+ if sys.version_info < (3, 11):
14
+ from exceptiongroup import ExceptionGroup
15
+
16
+ if TYPE_CHECKING:
17
+ from collections.abc import AsyncGenerator
18
+
19
+
20
+ async def test_channel() -> None:
21
+ with pytest.raises(TypeError):
22
+ open_memory_channel(1.0)
23
+ with pytest.raises(ValueError, match=r"^max_buffer_size must be >= 0$"):
24
+ open_memory_channel(-1)
25
+
26
+ s, r = open_memory_channel[int | str | None](2)
27
+ repr(s) # smoke test
28
+ repr(r) # smoke test
29
+
30
+ s.send_nowait(1)
31
+ with assert_checkpoints():
32
+ await s.send(2)
33
+ with pytest.raises(trio.WouldBlock):
34
+ s.send_nowait(None)
35
+
36
+ with assert_checkpoints():
37
+ assert await r.receive() == 1
38
+ assert r.receive_nowait() == 2
39
+ with pytest.raises(trio.WouldBlock):
40
+ r.receive_nowait()
41
+
42
+ s.send_nowait("last")
43
+ await s.aclose()
44
+ with pytest.raises(trio.ClosedResourceError):
45
+ await s.send("too late")
46
+ with pytest.raises(trio.ClosedResourceError):
47
+ s.send_nowait("too late")
48
+ with pytest.raises(trio.ClosedResourceError):
49
+ s.clone()
50
+ await s.aclose()
51
+
52
+ assert r.receive_nowait() == "last"
53
+ with pytest.raises(EndOfChannel):
54
+ await r.receive()
55
+ await r.aclose()
56
+ with pytest.raises(trio.ClosedResourceError):
57
+ await r.receive()
58
+ with pytest.raises(trio.ClosedResourceError):
59
+ r.receive_nowait()
60
+ await r.aclose()
61
+
62
+
63
+ async def test_553(autojump_clock: trio.abc.Clock) -> None:
64
+ s, r = open_memory_channel[str](1)
65
+ with trio.move_on_after(10) as timeout_scope:
66
+ await r.receive()
67
+ assert timeout_scope.cancelled_caught
68
+ await s.send("Test for PR #553")
69
+
70
+
71
+ async def test_channel_multiple_producers() -> None:
72
+ async def producer(send_channel: trio.MemorySendChannel[int], i: int) -> None:
73
+ # We close our handle when we're done with it
74
+ async with send_channel:
75
+ for j in range(3 * i, 3 * (i + 1)):
76
+ await send_channel.send(j)
77
+
78
+ send_channel, receive_channel = open_memory_channel[int](0)
79
+ async with trio.open_nursery() as nursery:
80
+ # We hand out clones to all the new producers, and then close the
81
+ # original.
82
+ async with send_channel:
83
+ for i in range(10):
84
+ nursery.start_soon(producer, send_channel.clone(), i)
85
+
86
+ got = [value async for value in receive_channel]
87
+
88
+ got.sort()
89
+ assert got == list(range(30))
90
+
91
+
92
+ async def test_channel_multiple_consumers() -> None:
93
+ successful_receivers = set()
94
+ received = []
95
+
96
+ async def consumer(receive_channel: trio.MemoryReceiveChannel[int], i: int) -> None:
97
+ async for value in receive_channel:
98
+ successful_receivers.add(i)
99
+ received.append(value)
100
+
101
+ async with trio.open_nursery() as nursery:
102
+ send_channel, receive_channel = trio.open_memory_channel[int](1)
103
+ async with send_channel:
104
+ for i in range(5):
105
+ nursery.start_soon(consumer, receive_channel, i)
106
+ await wait_all_tasks_blocked()
107
+ for i in range(10):
108
+ await send_channel.send(i)
109
+
110
+ assert successful_receivers == set(range(5))
111
+ assert len(received) == 10
112
+ assert set(received) == set(range(10))
113
+
114
+
115
+ async def test_close_basics() -> None:
116
+ async def send_block(
117
+ s: trio.MemorySendChannel[None],
118
+ expect: type[BaseException],
119
+ ) -> None:
120
+ with pytest.raises(expect):
121
+ await s.send(None)
122
+
123
+ # closing send -> other send gets ClosedResourceError
124
+ s, r = open_memory_channel[None](0)
125
+ async with trio.open_nursery() as nursery:
126
+ nursery.start_soon(send_block, s, trio.ClosedResourceError)
127
+ await wait_all_tasks_blocked()
128
+ await s.aclose()
129
+
130
+ # and it's persistent
131
+ with pytest.raises(trio.ClosedResourceError):
132
+ s.send_nowait(None)
133
+ with pytest.raises(trio.ClosedResourceError):
134
+ await s.send(None)
135
+
136
+ # and receive gets EndOfChannel
137
+ with pytest.raises(EndOfChannel):
138
+ r.receive_nowait()
139
+ with pytest.raises(EndOfChannel):
140
+ await r.receive()
141
+
142
+ # closing receive -> send gets BrokenResourceError
143
+ s, r = open_memory_channel[None](0)
144
+ async with trio.open_nursery() as nursery:
145
+ nursery.start_soon(send_block, s, trio.BrokenResourceError)
146
+ await wait_all_tasks_blocked()
147
+ await r.aclose()
148
+
149
+ # and it's persistent
150
+ with pytest.raises(trio.BrokenResourceError):
151
+ s.send_nowait(None)
152
+ with pytest.raises(trio.BrokenResourceError):
153
+ await s.send(None)
154
+
155
+ # closing receive -> other receive gets ClosedResourceError
156
+ async def receive_block(r: trio.MemoryReceiveChannel[int]) -> None:
157
+ with pytest.raises(trio.ClosedResourceError):
158
+ await r.receive()
159
+
160
+ _s2, r2 = open_memory_channel[int](0)
161
+ async with trio.open_nursery() as nursery:
162
+ nursery.start_soon(receive_block, r2)
163
+ await wait_all_tasks_blocked()
164
+ await r2.aclose()
165
+
166
+ # and it's persistent
167
+ with pytest.raises(trio.ClosedResourceError):
168
+ r2.receive_nowait()
169
+ with pytest.raises(trio.ClosedResourceError):
170
+ await r2.receive()
171
+
172
+
173
+ async def test_close_sync() -> None:
174
+ async def send_block(
175
+ s: trio.MemorySendChannel[None],
176
+ expect: type[BaseException],
177
+ ) -> None:
178
+ with pytest.raises(expect):
179
+ await s.send(None)
180
+
181
+ # closing send -> other send gets ClosedResourceError
182
+ s, r = open_memory_channel[None](0)
183
+ async with trio.open_nursery() as nursery:
184
+ nursery.start_soon(send_block, s, trio.ClosedResourceError)
185
+ await wait_all_tasks_blocked()
186
+ s.close()
187
+
188
+ # and it's persistent
189
+ with pytest.raises(trio.ClosedResourceError):
190
+ s.send_nowait(None)
191
+ with pytest.raises(trio.ClosedResourceError):
192
+ await s.send(None)
193
+
194
+ # and receive gets EndOfChannel
195
+ with pytest.raises(EndOfChannel):
196
+ r.receive_nowait()
197
+ with pytest.raises(EndOfChannel):
198
+ await r.receive()
199
+
200
+ # closing receive -> send gets BrokenResourceError
201
+ s, r = open_memory_channel[None](0)
202
+ async with trio.open_nursery() as nursery:
203
+ nursery.start_soon(send_block, s, trio.BrokenResourceError)
204
+ await wait_all_tasks_blocked()
205
+ r.close()
206
+
207
+ # and it's persistent
208
+ with pytest.raises(trio.BrokenResourceError):
209
+ s.send_nowait(None)
210
+ with pytest.raises(trio.BrokenResourceError):
211
+ await s.send(None)
212
+
213
+ # closing receive -> other receive gets ClosedResourceError
214
+ async def receive_block(r: trio.MemoryReceiveChannel[None]) -> None:
215
+ with pytest.raises(trio.ClosedResourceError):
216
+ await r.receive()
217
+
218
+ s, r = open_memory_channel[None](0)
219
+ async with trio.open_nursery() as nursery:
220
+ nursery.start_soon(receive_block, r)
221
+ await wait_all_tasks_blocked()
222
+ r.close()
223
+
224
+ # and it's persistent
225
+ with pytest.raises(trio.ClosedResourceError):
226
+ r.receive_nowait()
227
+ with pytest.raises(trio.ClosedResourceError):
228
+ await r.receive()
229
+
230
+
231
+ async def test_receive_channel_clone_and_close() -> None:
232
+ s, r = open_memory_channel[None](10)
233
+
234
+ r2 = r.clone()
235
+ r3 = r.clone()
236
+
237
+ s.send_nowait(None)
238
+ await r.aclose()
239
+ with r2:
240
+ pass
241
+
242
+ with pytest.raises(trio.ClosedResourceError):
243
+ r.clone()
244
+
245
+ with pytest.raises(trio.ClosedResourceError):
246
+ r2.clone()
247
+
248
+ # Can still send, r3 is still open
249
+ s.send_nowait(None)
250
+
251
+ await r3.aclose()
252
+
253
+ # But now the receiver is really closed
254
+ with pytest.raises(trio.BrokenResourceError):
255
+ s.send_nowait(None)
256
+
257
+
258
+ async def test_close_multiple_send_handles() -> None:
259
+ # With multiple send handles, closing one handle only wakes senders on
260
+ # that handle, but others can continue just fine
261
+ s1, r = open_memory_channel[str](0)
262
+ s2 = s1.clone()
263
+
264
+ async def send_will_close() -> None:
265
+ with pytest.raises(trio.ClosedResourceError):
266
+ await s1.send("nope")
267
+
268
+ async def send_will_succeed() -> None:
269
+ await s2.send("ok")
270
+
271
+ async with trio.open_nursery() as nursery:
272
+ nursery.start_soon(send_will_close)
273
+ nursery.start_soon(send_will_succeed)
274
+ await wait_all_tasks_blocked()
275
+ await s1.aclose()
276
+ assert await r.receive() == "ok"
277
+
278
+
279
+ async def test_close_multiple_receive_handles() -> None:
280
+ # With multiple receive handles, closing one handle only wakes receivers on
281
+ # that handle, but others can continue just fine
282
+ s, r1 = open_memory_channel[str](0)
283
+ r2 = r1.clone()
284
+
285
+ async def receive_will_close() -> None:
286
+ with pytest.raises(trio.ClosedResourceError):
287
+ await r1.receive()
288
+
289
+ async def receive_will_succeed() -> None:
290
+ assert await r2.receive() == "ok"
291
+
292
+ async with trio.open_nursery() as nursery:
293
+ nursery.start_soon(receive_will_close)
294
+ nursery.start_soon(receive_will_succeed)
295
+ await wait_all_tasks_blocked()
296
+ await r1.aclose()
297
+ await s.send("ok")
298
+
299
+
300
+ async def test_inf_capacity() -> None:
301
+ send, receive = open_memory_channel[int](float("inf"))
302
+
303
+ # It's accepted, and we can send all day without blocking
304
+ with send:
305
+ for i in range(10):
306
+ send.send_nowait(i)
307
+
308
+ got = [i async for i in receive]
309
+ assert got == list(range(10))
310
+
311
+
312
+ async def test_statistics() -> None:
313
+ s, r = open_memory_channel[None](2)
314
+
315
+ assert s.statistics() == r.statistics()
316
+ stats = s.statistics()
317
+ assert stats.current_buffer_used == 0
318
+ assert stats.max_buffer_size == 2
319
+ assert stats.open_send_channels == 1
320
+ assert stats.open_receive_channels == 1
321
+ assert stats.tasks_waiting_send == 0
322
+ assert stats.tasks_waiting_receive == 0
323
+
324
+ s.send_nowait(None)
325
+ assert s.statistics().current_buffer_used == 1
326
+
327
+ s2 = s.clone()
328
+ assert s.statistics().open_send_channels == 2
329
+ await s.aclose()
330
+ assert s2.statistics().open_send_channels == 1
331
+
332
+ r2 = r.clone()
333
+ assert s2.statistics().open_receive_channels == 2
334
+ await r2.aclose()
335
+ assert s2.statistics().open_receive_channels == 1
336
+
337
+ async with trio.open_nursery() as nursery:
338
+ s2.send_nowait(None) # fill up the buffer
339
+ assert s.statistics().current_buffer_used == 2
340
+ nursery.start_soon(s2.send, None)
341
+ nursery.start_soon(s2.send, None)
342
+ await wait_all_tasks_blocked()
343
+ assert s.statistics().tasks_waiting_send == 2
344
+ nursery.cancel_scope.cancel()
345
+ assert s.statistics().tasks_waiting_send == 0
346
+
347
+ # empty out the buffer again
348
+ try:
349
+ while True:
350
+ r.receive_nowait()
351
+ except trio.WouldBlock:
352
+ pass
353
+
354
+ async with trio.open_nursery() as nursery:
355
+ nursery.start_soon(r.receive)
356
+ await wait_all_tasks_blocked()
357
+ assert s.statistics().tasks_waiting_receive == 1
358
+ nursery.cancel_scope.cancel()
359
+ assert s.statistics().tasks_waiting_receive == 0
360
+
361
+
362
+ async def test_channel_fairness() -> None:
363
+ # We can remove an item we just sent, and send an item back in after, if
364
+ # no-one else is waiting.
365
+ s, r = open_memory_channel[int | None](1)
366
+ s.send_nowait(1)
367
+ assert r.receive_nowait() == 1
368
+ s.send_nowait(2)
369
+ assert r.receive_nowait() == 2
370
+
371
+ # But if someone else is waiting to receive, then they "own" the item we
372
+ # send, so we can't receive it (even though we run first):
373
+
374
+ result: int | None = None
375
+
376
+ async def do_receive(r: trio.MemoryReceiveChannel[int | None]) -> None:
377
+ nonlocal result
378
+ result = await r.receive()
379
+
380
+ async with trio.open_nursery() as nursery:
381
+ nursery.start_soon(do_receive, r)
382
+ await wait_all_tasks_blocked()
383
+ s.send_nowait(2)
384
+ with pytest.raises(trio.WouldBlock):
385
+ r.receive_nowait()
386
+ assert result == 2
387
+
388
+ # And the analogous situation for send: if we free up a space, we can't
389
+ # immediately send something in it if someone is already waiting to do
390
+ # that
391
+ s, r = open_memory_channel[int | None](1)
392
+ s.send_nowait(1)
393
+ with pytest.raises(trio.WouldBlock):
394
+ s.send_nowait(None)
395
+ async with trio.open_nursery() as nursery:
396
+ nursery.start_soon(s.send, 2)
397
+ await wait_all_tasks_blocked()
398
+ assert r.receive_nowait() == 1
399
+ with pytest.raises(trio.WouldBlock):
400
+ s.send_nowait(3)
401
+ assert (await r.receive()) == 2
402
+
403
+
404
+ async def test_unbuffered() -> None:
405
+ s, r = open_memory_channel[int](0)
406
+ with pytest.raises(trio.WouldBlock):
407
+ r.receive_nowait()
408
+ with pytest.raises(trio.WouldBlock):
409
+ s.send_nowait(1)
410
+
411
+ async def do_send(s: trio.MemorySendChannel[int], v: int) -> None:
412
+ with assert_checkpoints():
413
+ await s.send(v)
414
+
415
+ async with trio.open_nursery() as nursery:
416
+ nursery.start_soon(do_send, s, 1)
417
+ with assert_checkpoints():
418
+ assert await r.receive() == 1
419
+ with pytest.raises(trio.WouldBlock):
420
+ r.receive_nowait()
421
+
422
+
423
+ async def test_as_safe_channel_exhaust() -> None:
424
+ @as_safe_channel
425
+ async def agen() -> AsyncGenerator[int]:
426
+ yield 1
427
+
428
+ async with agen() as recv_chan:
429
+ async for x in recv_chan:
430
+ assert x == 1
431
+
432
+
433
+ async def test_as_safe_channel_broken_resource() -> None:
434
+ @as_safe_channel
435
+ async def agen() -> AsyncGenerator[int]:
436
+ yield 1
437
+ yield 2 # pragma: no cover
438
+
439
+ async with agen() as recv_chan:
440
+ assert await recv_chan.__anext__() == 1
441
+
442
+ # close the receiving channel
443
+ await recv_chan.aclose()
444
+
445
+ # trying to get the next element errors
446
+ with pytest.raises(trio.ClosedResourceError):
447
+ await recv_chan.__anext__()
448
+
449
+ # but we don't get an error on exit of the cm
450
+
451
+
452
+ async def test_as_safe_channel_cancelled() -> None:
453
+ with trio.CancelScope() as cs:
454
+
455
+ @as_safe_channel
456
+ async def agen() -> AsyncGenerator[None]: # pragma: no cover
457
+ raise AssertionError(
458
+ "cancel before consumption means generator should not be iterated"
459
+ )
460
+ yield # indicate that we're an iterator
461
+
462
+ async with agen():
463
+ cs.cancel()
464
+
465
+
466
+ async def test_as_safe_channel_no_race() -> None:
467
+ # this previously led to a race condition due to
468
+ # https://github.com/python-trio/trio/issues/1559
469
+ @as_safe_channel
470
+ async def agen() -> AsyncGenerator[int]:
471
+ yield 1
472
+ raise ValueError("oae")
473
+
474
+ with pytest.raises(ValueError, match=r"^oae$"):
475
+ async with agen() as recv_chan:
476
+ async for x in recv_chan:
477
+ assert x == 1
478
+
479
+
480
+ async def test_as_safe_channel_buffer_size_too_small(
481
+ autojump_clock: trio.testing.MockClock,
482
+ ) -> None:
483
+ @as_safe_channel
484
+ async def agen() -> AsyncGenerator[int]:
485
+ yield 1
486
+ raise AssertionError(
487
+ "buffer size 0 means we shouldn't be asked for another value"
488
+ ) # pragma: no cover
489
+
490
+ with trio.move_on_after(5):
491
+ async with agen() as recv_chan:
492
+ async for x in recv_chan: # pragma: no branch
493
+ assert x == 1
494
+ await trio.sleep_forever()
495
+
496
+
497
+ async def test_as_safe_channel_no_interleave() -> None:
498
+ @as_safe_channel
499
+ async def agen() -> AsyncGenerator[int]:
500
+ yield 1
501
+ raise AssertionError # pragma: no cover
502
+
503
+ async with agen() as recv_chan:
504
+ assert await recv_chan.__anext__() == 1
505
+ await trio.lowlevel.checkpoint()
506
+
507
+
508
+ async def test_as_safe_channel_genexit_finally() -> None:
509
+ @as_safe_channel
510
+ async def agen(events: list[str]) -> AsyncGenerator[int]:
511
+ try:
512
+ yield 1
513
+ except BaseException as e:
514
+ events.append(repr(e))
515
+ raise
516
+ finally:
517
+ events.append("finally")
518
+ raise ValueError("agen")
519
+
520
+ events: list[str] = []
521
+ with pytest.RaisesGroup(
522
+ pytest.RaisesExc(ValueError, match="^agen$"),
523
+ pytest.RaisesExc(TypeError, match="^iterator$"),
524
+ ) as g:
525
+ async with agen(events) as recv_chan:
526
+ async for i in recv_chan: # pragma: no branch
527
+ assert i == 1
528
+ raise TypeError("iterator")
529
+
530
+ if sys.version_info >= (3, 11):
531
+ assert g.value.__notes__ == [
532
+ "Encountered exception during cleanup of generator object, as "
533
+ "well as exception in the contextmanager body - unable to unwrap."
534
+ ]
535
+
536
+ assert events == ["GeneratorExit()", "finally"]
537
+
538
+
539
+ async def test_as_safe_channel_nested_loop() -> None:
540
+ @as_safe_channel
541
+ async def agen() -> AsyncGenerator[int]:
542
+ for i in range(2):
543
+ yield i
544
+
545
+ ii = 0
546
+ async with agen() as recv_chan1:
547
+ async for i in recv_chan1:
548
+ async with agen() as recv_chan:
549
+ jj = 0
550
+ async for j in recv_chan:
551
+ assert (i, j) == (ii, jj)
552
+ jj += 1
553
+ ii += 1
554
+
555
+
556
+ async def test_as_safe_channel_doesnt_leak_cancellation() -> None:
557
+ @as_safe_channel
558
+ async def agen() -> AsyncGenerator[None]:
559
+ yield
560
+ with trio.CancelScope() as cscope:
561
+ cscope.cancel()
562
+ yield
563
+
564
+ with pytest.raises(AssertionError):
565
+ async with agen() as recv_chan:
566
+ async for _ in recv_chan:
567
+ pass
568
+ raise AssertionError("should be reachable")
569
+
570
+
571
+ async def test_as_safe_channel_dont_unwrap_user_exceptiongroup() -> None:
572
+ @as_safe_channel
573
+ async def agen() -> AsyncGenerator[None]:
574
+ raise NotImplementedError("not entered")
575
+ yield # pragma: no cover
576
+
577
+ with pytest.RaisesGroup(pytest.RaisesExc(ValueError, match="bar"), match="foo"):
578
+ async with agen() as _:
579
+ raise ExceptionGroup("foo", [ValueError("bar")])
580
+
581
+
582
+ async def test_as_safe_channel_multiple_receiver() -> None:
583
+ event = trio.Event()
584
+
585
+ @as_safe_channel
586
+ async def agen() -> AsyncGenerator[int]:
587
+ await event.wait()
588
+ yield 0
589
+ yield 1
590
+
591
+ async def handle_value(
592
+ recv_chan: trio.abc.ReceiveChannel[int],
593
+ value: int,
594
+ task_status: trio.TaskStatus,
595
+ ) -> None:
596
+ task_status.started()
597
+ assert await recv_chan.receive() == value
598
+
599
+ async with agen() as recv_chan:
600
+ async with trio.open_nursery() as nursery:
601
+ await nursery.start(handle_value, recv_chan, 0)
602
+ await nursery.start(handle_value, recv_chan, 1)
603
+ event.set()
604
+
605
+
606
+ async def test_as_safe_channel_multi_cancel() -> None:
607
+ @as_safe_channel
608
+ async def agen(events: list[str]) -> AsyncGenerator[None]:
609
+ try:
610
+ yield
611
+ finally:
612
+ # this will give a warning of ASYNC120, although it's not technically a
613
+ # problem of swallowing existing exceptions
614
+ try:
615
+ await trio.lowlevel.checkpoint()
616
+ except trio.Cancelled:
617
+ events.append("agen cancel")
618
+ raise
619
+
620
+ events: list[str] = []
621
+ with trio.CancelScope() as cs:
622
+ with pytest.raises(trio.Cancelled):
623
+ async with agen(events) as recv_chan:
624
+ async for _ in recv_chan: # pragma: no branch
625
+ cs.cancel()
626
+ try:
627
+ await trio.lowlevel.checkpoint()
628
+ except trio.Cancelled:
629
+ events.append("body cancel")
630
+ raise
631
+ assert events == ["body cancel", "agen cancel"]
632
+
633
+
634
+ async def test_as_safe_channel_genexit_exception_group() -> None:
635
+ @as_safe_channel
636
+ async def agen() -> AsyncGenerator[None]:
637
+ try:
638
+ async with trio.open_nursery():
639
+ yield
640
+ except BaseException as e:
641
+ assert pytest.RaisesGroup(GeneratorExit).matches(e) # noqa: PT017
642
+ raise
643
+
644
+ async with agen() as g:
645
+ async for _ in g:
646
+ break
647
+
648
+
649
+ async def test_as_safe_channel_does_not_suppress_nested_genexit() -> None:
650
+ @as_safe_channel
651
+ async def agen() -> AsyncGenerator[None]:
652
+ yield
653
+
654
+ with pytest.RaisesGroup(GeneratorExit):
655
+ async with agen() as g, trio.open_nursery():
656
+ await g.receive() # this is for coverage reasons
657
+ raise GeneratorExit
658
+
659
+
660
+ async def test_as_safe_channel_genexit_filter() -> None:
661
+ async def wait_then_raise() -> None:
662
+ try:
663
+ await trio.sleep_forever()
664
+ except trio.Cancelled:
665
+ raise ValueError from None
666
+
667
+ @as_safe_channel
668
+ async def agen() -> AsyncGenerator[None]:
669
+ async with trio.open_nursery() as nursery:
670
+ nursery.start_soon(wait_then_raise)
671
+ yield
672
+
673
+ with pytest.RaisesGroup(ValueError):
674
+ async with agen() as g:
675
+ async for _ in g:
676
+ break
677
+
678
+
679
+ async def test_as_safe_channel_swallowing_extra_exceptions() -> None:
680
+ async def wait_then_raise(ex: type[BaseException]) -> None:
681
+ try:
682
+ await trio.sleep_forever()
683
+ except trio.Cancelled:
684
+ raise ex from None
685
+
686
+ @as_safe_channel
687
+ async def agen(ex: type[BaseException]) -> AsyncGenerator[None]:
688
+ async with trio.open_nursery() as nursery:
689
+ nursery.start_soon(wait_then_raise, ex)
690
+ nursery.start_soon(wait_then_raise, GeneratorExit)
691
+ yield
692
+
693
+ with pytest.RaisesGroup(AssertionError):
694
+ async with agen(GeneratorExit) as g:
695
+ async for _ in g:
696
+ break
697
+
698
+ with pytest.RaisesGroup(ValueError, AssertionError):
699
+ async with agen(ValueError) as g:
700
+ async for _ in g:
701
+ break
702
+
703
+
704
+ async def test_as_safe_channel_close_between_iteration() -> None:
705
+ @as_safe_channel
706
+ async def agen() -> AsyncGenerator[None]:
707
+ while True:
708
+ yield
709
+
710
+ async with agen() as chan, trio.open_nursery() as nursery:
711
+
712
+ async def close_channel() -> None:
713
+ await trio.lowlevel.checkpoint()
714
+ await chan.aclose()
715
+
716
+ nursery.start_soon(close_channel)
717
+ with pytest.raises(trio.ClosedResourceError):
718
+ async for _ in chan:
719
+ pass
720
+
721
+
722
+ async def test_as_safe_channel_close_before_iteration() -> None:
723
+ @as_safe_channel
724
+ async def agen() -> AsyncGenerator[None]:
725
+ raise AssertionError("should be unreachable") # pragma: no cover
726
+ yield # pragma: no cover
727
+
728
+ async with agen() as chan:
729
+ await chan.aclose()
730
+ with pytest.raises(trio.ClosedResourceError):
731
+ await chan.receive()
732
+
733
+
734
+ async def test_as_safe_channel_close_during_iteration() -> None:
735
+ @as_safe_channel
736
+ async def agen() -> AsyncGenerator[None]:
737
+ yield
738
+ await chan.aclose()
739
+ while True:
740
+ yield
741
+
742
+ async with agen() as chan:
743
+ with pytest.raises(trio.ClosedResourceError):
744
+ async for _ in chan:
745
+ pass
746
+
747
+ # This is necessary to ensure that `chan` has been sent
748
+ # to. Otherwise, this test sometimes passes on a broken
749
+ # version of trio.
750
+ await trio.testing.wait_all_tasks_blocked()