@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,58 @@
1
+ # Uses `from x import y as y` for compatibility with `pyright --verifytypes` (#2625)
2
+
3
+ from .. import _deprecate as _deprecate
4
+ from .._core import (
5
+ MockClock as MockClock,
6
+ wait_all_tasks_blocked as wait_all_tasks_blocked,
7
+ )
8
+ from .._threads import (
9
+ active_thread_count as active_thread_count,
10
+ wait_all_threads_completed as wait_all_threads_completed,
11
+ )
12
+ from .._util import fixup_module_metadata
13
+ from ._check_streams import (
14
+ check_half_closeable_stream as check_half_closeable_stream,
15
+ check_one_way_stream as check_one_way_stream,
16
+ check_two_way_stream as check_two_way_stream,
17
+ )
18
+ from ._checkpoints import (
19
+ assert_checkpoints as assert_checkpoints,
20
+ assert_no_checkpoints as assert_no_checkpoints,
21
+ )
22
+ from ._memory_streams import (
23
+ MemoryReceiveStream as MemoryReceiveStream,
24
+ MemorySendStream as MemorySendStream,
25
+ lockstep_stream_one_way_pair as lockstep_stream_one_way_pair,
26
+ lockstep_stream_pair as lockstep_stream_pair,
27
+ memory_stream_one_way_pair as memory_stream_one_way_pair,
28
+ memory_stream_pair as memory_stream_pair,
29
+ memory_stream_pump as memory_stream_pump,
30
+ )
31
+ from ._network import open_stream_to_socket_listener as open_stream_to_socket_listener
32
+ from ._raises_group import Matcher as _Matcher, RaisesGroup as _RaisesGroup
33
+ from ._sequencer import Sequencer as Sequencer
34
+ from ._trio_test import trio_test as trio_test
35
+
36
+ ################################################################
37
+
38
+
39
+ _deprecate.deprecate_attributes(
40
+ __name__,
41
+ {
42
+ "RaisesGroup": _deprecate.DeprecatedAttribute(
43
+ _RaisesGroup,
44
+ version="0.33.0",
45
+ issue=3326,
46
+ instead="See https://docs.pytest.org/en/stable/reference/reference.html#pytest.RaisesGroup",
47
+ ),
48
+ "Matcher": _deprecate.DeprecatedAttribute(
49
+ _Matcher,
50
+ version="0.33.0",
51
+ issue=3326,
52
+ instead="See https://docs.pytest.org/en/stable/reference/reference.html#pytest.RaisesExc",
53
+ ),
54
+ },
55
+ )
56
+
57
+ fixup_module_metadata(__name__, globals())
58
+ del fixup_module_metadata
@@ -0,0 +1,570 @@
1
+ # Generic stream tests
2
+ from __future__ import annotations
3
+
4
+ import random
5
+ import sys
6
+ from collections.abc import Awaitable, Callable, Generator
7
+ from contextlib import contextmanager, suppress
8
+ from typing import (
9
+ TYPE_CHECKING,
10
+ Generic,
11
+ TypeAlias,
12
+ TypeVar,
13
+ )
14
+
15
+ from .. import CancelScope, _core
16
+ from .._abc import AsyncResource, HalfCloseableStream, ReceiveStream, SendStream, Stream
17
+ from .._highlevel_generic import aclose_forcefully
18
+ from ._checkpoints import assert_checkpoints
19
+
20
+ if TYPE_CHECKING:
21
+ from types import TracebackType
22
+
23
+ from typing_extensions import ParamSpec
24
+
25
+ ArgsT = ParamSpec("ArgsT")
26
+
27
+ if sys.version_info < (3, 11):
28
+ from exceptiongroup import BaseExceptionGroup
29
+
30
+ Res1 = TypeVar("Res1", bound=AsyncResource)
31
+ Res2 = TypeVar("Res2", bound=AsyncResource)
32
+ StreamMaker: TypeAlias = Callable[[], Awaitable[tuple[Res1, Res2]]]
33
+
34
+
35
+ class _ForceCloseBoth(Generic[Res1, Res2]):
36
+ def __init__(self, both: tuple[Res1, Res2]) -> None:
37
+ self._first, self._second = both
38
+
39
+ async def __aenter__(self) -> tuple[Res1, Res2]:
40
+ return self._first, self._second
41
+
42
+ async def __aexit__(
43
+ self,
44
+ exc_type: type[BaseException] | None,
45
+ exc_value: BaseException | None,
46
+ traceback: TracebackType | None,
47
+ ) -> None:
48
+ try:
49
+ await aclose_forcefully(self._first)
50
+ finally:
51
+ await aclose_forcefully(self._second)
52
+
53
+
54
+ # This is used in this file instead of pytest.raises in order to avoid a dependency
55
+ # on pytest, as the check_* functions are publicly exported.
56
+ @contextmanager
57
+ def _assert_raises(
58
+ expected_exc: type[BaseException],
59
+ wrapped: bool = False,
60
+ ) -> Generator[None, None, None]:
61
+ __tracebackhide__ = True
62
+ try:
63
+ yield
64
+ except BaseExceptionGroup as exc:
65
+ assert wrapped, "caught exceptiongroup, but expected an unwrapped exception"
66
+ # assert in except block ignored below
67
+ assert len(exc.exceptions) == 1 # noqa: PT017
68
+ assert isinstance(exc.exceptions[0], expected_exc) # noqa: PT017
69
+ except expected_exc:
70
+ assert not wrapped, "caught exception, but expected an exceptiongroup"
71
+ else:
72
+ raise AssertionError(f"expected exception: {expected_exc}")
73
+
74
+
75
+ async def check_one_way_stream(
76
+ stream_maker: StreamMaker[SendStream, ReceiveStream],
77
+ clogged_stream_maker: StreamMaker[SendStream, ReceiveStream] | None,
78
+ ) -> None:
79
+ """Perform a number of generic tests on a custom one-way stream
80
+ implementation.
81
+
82
+ Args:
83
+ stream_maker: An async (!) function which returns a connected
84
+ (:class:`~trio.abc.SendStream`, :class:`~trio.abc.ReceiveStream`)
85
+ pair.
86
+ clogged_stream_maker: Either None, or an async function similar to
87
+ stream_maker, but with the extra property that the returned stream
88
+ is in a state where ``send_all`` and
89
+ ``wait_send_all_might_not_block`` will block until ``receive_some``
90
+ has been called. This allows for more thorough testing of some edge
91
+ cases, especially around ``wait_send_all_might_not_block``.
92
+
93
+ Raises:
94
+ AssertionError: if a test fails.
95
+
96
+ """
97
+ async with _ForceCloseBoth(await stream_maker()) as (s, r):
98
+ assert isinstance(s, SendStream)
99
+ assert isinstance(r, ReceiveStream)
100
+
101
+ async def do_send_all(data: bytes | bytearray | memoryview) -> None:
102
+ with assert_checkpoints(): # We're testing that it doesn't return anything.
103
+ assert await s.send_all(data) is None # type: ignore[func-returns-value]
104
+
105
+ async def do_receive_some(max_bytes: int | None = None) -> bytes | bytearray:
106
+ with assert_checkpoints():
107
+ return await r.receive_some(max_bytes)
108
+
109
+ async def checked_receive_1(expected: bytes) -> None:
110
+ assert await do_receive_some(1) == expected
111
+
112
+ async def do_aclose(resource: AsyncResource) -> None:
113
+ with assert_checkpoints():
114
+ await resource.aclose()
115
+
116
+ # Simple sending/receiving
117
+ async with _core.open_nursery() as nursery:
118
+ nursery.start_soon(do_send_all, b"x")
119
+ nursery.start_soon(checked_receive_1, b"x")
120
+
121
+ async def send_empty_then_y() -> None:
122
+ # Streams should tolerate sending b"" without giving it any
123
+ # special meaning.
124
+ await do_send_all(b"")
125
+ await do_send_all(b"y")
126
+
127
+ async with _core.open_nursery() as nursery:
128
+ nursery.start_soon(send_empty_then_y)
129
+ nursery.start_soon(checked_receive_1, b"y")
130
+
131
+ # ---- Checking various argument types ----
132
+
133
+ # send_all accepts bytearray and memoryview
134
+ async with _core.open_nursery() as nursery:
135
+ nursery.start_soon(do_send_all, bytearray(b"1"))
136
+ nursery.start_soon(checked_receive_1, b"1")
137
+
138
+ async with _core.open_nursery() as nursery:
139
+ nursery.start_soon(do_send_all, memoryview(b"2"))
140
+ nursery.start_soon(checked_receive_1, b"2")
141
+
142
+ # max_bytes must be a positive integer
143
+ with _assert_raises(ValueError):
144
+ await r.receive_some(-1)
145
+ with _assert_raises(ValueError):
146
+ await r.receive_some(0)
147
+ with _assert_raises(TypeError):
148
+ await r.receive_some(1.5) # type: ignore[arg-type]
149
+ # it can also be missing or None
150
+ async with _core.open_nursery() as nursery:
151
+ nursery.start_soon(do_send_all, b"x")
152
+ assert await do_receive_some() == b"x"
153
+ async with _core.open_nursery() as nursery:
154
+ nursery.start_soon(do_send_all, b"x")
155
+ assert await do_receive_some(None) == b"x"
156
+
157
+ with _assert_raises(_core.BusyResourceError, wrapped=True):
158
+ async with _core.open_nursery() as nursery:
159
+ nursery.start_soon(do_receive_some, 1)
160
+ nursery.start_soon(do_receive_some, 1)
161
+
162
+ # Method always has to exist, and an empty stream with a blocked
163
+ # receive_some should *always* allow send_all. (Technically it's legal
164
+ # for send_all to wait until receive_some is called to run, though; a
165
+ # stream doesn't *have* to have any internal buffering. That's why we
166
+ # start a concurrent receive_some call, then cancel it.)
167
+ async def simple_check_wait_send_all_might_not_block(
168
+ scope: CancelScope,
169
+ ) -> None:
170
+ with assert_checkpoints():
171
+ await s.wait_send_all_might_not_block()
172
+ scope.cancel()
173
+
174
+ async with _core.open_nursery() as nursery:
175
+ nursery.start_soon(
176
+ simple_check_wait_send_all_might_not_block,
177
+ nursery.cancel_scope,
178
+ )
179
+ nursery.start_soon(do_receive_some, 1)
180
+
181
+ # closing the r side leads to BrokenResourceError on the s side
182
+ # (eventually)
183
+ async def expect_broken_stream_on_send() -> None:
184
+ with _assert_raises(_core.BrokenResourceError):
185
+ while True:
186
+ await do_send_all(b"x" * 100)
187
+
188
+ async with _core.open_nursery() as nursery:
189
+ nursery.start_soon(expect_broken_stream_on_send)
190
+ nursery.start_soon(do_aclose, r)
191
+
192
+ # once detected, the stream stays broken
193
+ with _assert_raises(_core.BrokenResourceError):
194
+ await do_send_all(b"x" * 100)
195
+
196
+ # r closed -> ClosedResourceError on the receive side
197
+ with _assert_raises(_core.ClosedResourceError):
198
+ await do_receive_some(4096)
199
+
200
+ # we can close the same stream repeatedly, it's fine
201
+ await do_aclose(r)
202
+ await do_aclose(r)
203
+
204
+ # closing the sender side
205
+ await do_aclose(s)
206
+
207
+ # now trying to send raises ClosedResourceError
208
+ with _assert_raises(_core.ClosedResourceError):
209
+ await do_send_all(b"x" * 100)
210
+
211
+ # even if it's an empty send
212
+ with _assert_raises(_core.ClosedResourceError):
213
+ await do_send_all(b"")
214
+
215
+ # ditto for wait_send_all_might_not_block
216
+ with _assert_raises(_core.ClosedResourceError):
217
+ with assert_checkpoints():
218
+ await s.wait_send_all_might_not_block()
219
+
220
+ # and again, repeated closing is fine
221
+ await do_aclose(s)
222
+ await do_aclose(s)
223
+
224
+ async with _ForceCloseBoth(await stream_maker()) as (s, r):
225
+ # if send-then-graceful-close, receiver gets data then b""
226
+ async def send_then_close() -> None:
227
+ await do_send_all(b"y")
228
+ await do_aclose(s)
229
+
230
+ async def receive_send_then_close() -> None:
231
+ # We want to make sure that if the sender closes the stream before
232
+ # we read anything, then we still get all the data. But some
233
+ # streams might block on the do_send_all call. So we let the
234
+ # sender get as far as it can, then we receive.
235
+ await _core.wait_all_tasks_blocked()
236
+ await checked_receive_1(b"y")
237
+ await checked_receive_1(b"")
238
+ await do_aclose(r)
239
+
240
+ async with _core.open_nursery() as nursery:
241
+ nursery.start_soon(send_then_close)
242
+ nursery.start_soon(receive_send_then_close)
243
+
244
+ async with _ForceCloseBoth(await stream_maker()) as (s, r):
245
+ await aclose_forcefully(r)
246
+
247
+ with _assert_raises(_core.BrokenResourceError):
248
+ while True:
249
+ await do_send_all(b"x" * 100)
250
+
251
+ with _assert_raises(_core.ClosedResourceError):
252
+ await do_receive_some(4096)
253
+
254
+ async with _ForceCloseBoth(await stream_maker()) as (s, r):
255
+ await aclose_forcefully(s)
256
+
257
+ with _assert_raises(_core.ClosedResourceError):
258
+ await do_send_all(b"123")
259
+
260
+ # after the sender does a forceful close, the receiver might either
261
+ # get BrokenResourceError or a clean b""; either is OK. Not OK would be
262
+ # if it freezes, or returns data.
263
+ with suppress(_core.BrokenResourceError):
264
+ await checked_receive_1(b"")
265
+
266
+ # cancelled aclose still closes
267
+ async with _ForceCloseBoth(await stream_maker()) as (s, r):
268
+ with _core.CancelScope() as scope:
269
+ scope.cancel()
270
+ await r.aclose()
271
+
272
+ with _core.CancelScope() as scope:
273
+ scope.cancel()
274
+ await s.aclose()
275
+
276
+ with _assert_raises(_core.ClosedResourceError):
277
+ await do_send_all(b"123")
278
+
279
+ with _assert_raises(_core.ClosedResourceError):
280
+ await do_receive_some(4096)
281
+
282
+ # Check that we can still gracefully close a stream after an operation has
283
+ # been cancelled. This can be challenging if cancellation can leave the
284
+ # stream internals in an inconsistent state, e.g. for
285
+ # SSLStream. Unfortunately this test isn't very thorough; the really
286
+ # challenging case for something like SSLStream is it gets cancelled
287
+ # *while* it's sending data on the underlying, not before. But testing
288
+ # that requires some special-case handling of the particular stream setup;
289
+ # we can't do it here. Maybe we could do a bit better with
290
+ # https://github.com/python-trio/trio/issues/77
291
+ async with _ForceCloseBoth(await stream_maker()) as (s, r):
292
+
293
+ async def expect_cancelled(
294
+ afn: Callable[ArgsT, Awaitable[object]],
295
+ *args: ArgsT.args,
296
+ **kwargs: ArgsT.kwargs,
297
+ ) -> None:
298
+ with _assert_raises(_core.Cancelled):
299
+ await afn(*args, **kwargs)
300
+
301
+ with _core.CancelScope() as scope:
302
+ scope.cancel()
303
+ async with _core.open_nursery() as nursery:
304
+ nursery.start_soon(expect_cancelled, do_send_all, b"x")
305
+ nursery.start_soon(expect_cancelled, do_receive_some, 1)
306
+
307
+ async with _core.open_nursery() as nursery:
308
+ nursery.start_soon(do_aclose, s)
309
+ nursery.start_soon(do_aclose, r)
310
+
311
+ # Check that if a task is blocked in receive_some, then closing the
312
+ # receive stream causes it to wake up.
313
+ async with _ForceCloseBoth(await stream_maker()) as (s, r):
314
+
315
+ async def receive_expecting_closed() -> None:
316
+ with _assert_raises(_core.ClosedResourceError):
317
+ await r.receive_some(10)
318
+
319
+ async with _core.open_nursery() as nursery:
320
+ nursery.start_soon(receive_expecting_closed)
321
+ await _core.wait_all_tasks_blocked()
322
+ await aclose_forcefully(r)
323
+
324
+ # check wait_send_all_might_not_block, if we can
325
+ if clogged_stream_maker is not None:
326
+ async with _ForceCloseBoth(await clogged_stream_maker()) as (s, r):
327
+ record: list[str] = []
328
+
329
+ async def waiter(cancel_scope: CancelScope) -> None:
330
+ record.append("waiter sleeping")
331
+ with assert_checkpoints():
332
+ await s.wait_send_all_might_not_block()
333
+ record.append("waiter wokeup")
334
+ cancel_scope.cancel()
335
+
336
+ async def receiver() -> None:
337
+ # give wait_send_all_might_not_block a chance to block
338
+ await _core.wait_all_tasks_blocked()
339
+ record.append("receiver starting")
340
+ while True:
341
+ await r.receive_some(16834)
342
+
343
+ async with _core.open_nursery() as nursery:
344
+ nursery.start_soon(waiter, nursery.cancel_scope)
345
+ await _core.wait_all_tasks_blocked()
346
+ nursery.start_soon(receiver)
347
+
348
+ assert record == [
349
+ "waiter sleeping",
350
+ "receiver starting",
351
+ "waiter wokeup",
352
+ ]
353
+
354
+ async with _ForceCloseBoth(await clogged_stream_maker()) as (s, r):
355
+ # simultaneous wait_send_all_might_not_block fails
356
+ with _assert_raises(_core.BusyResourceError, wrapped=True):
357
+ async with _core.open_nursery() as nursery:
358
+ nursery.start_soon(s.wait_send_all_might_not_block)
359
+ nursery.start_soon(s.wait_send_all_might_not_block)
360
+
361
+ # and simultaneous send_all and wait_send_all_might_not_block (NB
362
+ # this test might destroy the stream b/c we end up cancelling
363
+ # send_all and e.g. SSLStream can't handle that, so we have to
364
+ # recreate afterwards)
365
+ with _assert_raises(_core.BusyResourceError, wrapped=True):
366
+ async with _core.open_nursery() as nursery:
367
+ nursery.start_soon(s.wait_send_all_might_not_block)
368
+ nursery.start_soon(s.send_all, b"123")
369
+
370
+ async with _ForceCloseBoth(await clogged_stream_maker()) as (s, r):
371
+ # send_all and send_all blocked simultaneously should also raise
372
+ # (but again this might destroy the stream)
373
+ with _assert_raises(_core.BusyResourceError, wrapped=True):
374
+ async with _core.open_nursery() as nursery:
375
+ nursery.start_soon(s.send_all, b"123")
376
+ nursery.start_soon(s.send_all, b"123")
377
+
378
+ # closing the receiver causes wait_send_all_might_not_block to return,
379
+ # with or without an exception
380
+ async with _ForceCloseBoth(await clogged_stream_maker()) as (s, r):
381
+
382
+ async def sender() -> None:
383
+ try:
384
+ with assert_checkpoints():
385
+ await s.wait_send_all_might_not_block()
386
+ except _core.BrokenResourceError: # pragma: no cover
387
+ pass
388
+
389
+ async def receiver() -> None:
390
+ await _core.wait_all_tasks_blocked()
391
+ await aclose_forcefully(r)
392
+
393
+ async with _core.open_nursery() as nursery:
394
+ nursery.start_soon(sender)
395
+ nursery.start_soon(receiver)
396
+
397
+ # and again with the call starting after the close
398
+ async with _ForceCloseBoth(await clogged_stream_maker()) as (s, r):
399
+ await aclose_forcefully(r)
400
+ try:
401
+ with assert_checkpoints():
402
+ await s.wait_send_all_might_not_block()
403
+ except _core.BrokenResourceError: # pragma: no cover
404
+ pass
405
+
406
+ # Check that if a task is blocked in a send-side method, then closing
407
+ # the send stream causes it to wake up.
408
+ async def close_soon(s: SendStream) -> None:
409
+ await _core.wait_all_tasks_blocked()
410
+ await aclose_forcefully(s)
411
+
412
+ async with _ForceCloseBoth(await clogged_stream_maker()) as (s, r):
413
+ async with _core.open_nursery() as nursery:
414
+ nursery.start_soon(close_soon, s)
415
+ with _assert_raises(_core.ClosedResourceError):
416
+ await s.send_all(b"xyzzy")
417
+
418
+ async with _ForceCloseBoth(await clogged_stream_maker()) as (s, r):
419
+ async with _core.open_nursery() as nursery:
420
+ nursery.start_soon(close_soon, s)
421
+ with _assert_raises(_core.ClosedResourceError):
422
+ await s.wait_send_all_might_not_block()
423
+
424
+
425
+ async def check_two_way_stream(
426
+ stream_maker: StreamMaker[Stream, Stream],
427
+ clogged_stream_maker: StreamMaker[Stream, Stream] | None,
428
+ ) -> None:
429
+ """Perform a number of generic tests on a custom two-way stream
430
+ implementation.
431
+
432
+ This is similar to :func:`check_one_way_stream`, except that the maker
433
+ functions are expected to return objects implementing the
434
+ :class:`~trio.abc.Stream` interface.
435
+
436
+ This function tests a *superset* of what :func:`check_one_way_stream`
437
+ checks – if you call this, then you don't need to also call
438
+ :func:`check_one_way_stream`.
439
+
440
+ """
441
+ await check_one_way_stream(stream_maker, clogged_stream_maker)
442
+
443
+ async def flipped_stream_maker() -> tuple[Stream, Stream]:
444
+ return (await stream_maker())[::-1]
445
+
446
+ flipped_clogged_stream_maker: Callable[[], Awaitable[tuple[Stream, Stream]]] | None
447
+
448
+ if clogged_stream_maker is not None:
449
+
450
+ async def flipped_clogged_stream_maker() -> tuple[Stream, Stream]:
451
+ return (await clogged_stream_maker())[::-1]
452
+
453
+ else:
454
+ flipped_clogged_stream_maker = None
455
+ await check_one_way_stream(flipped_stream_maker, flipped_clogged_stream_maker)
456
+
457
+ async with _ForceCloseBoth(await stream_maker()) as (s1, s2):
458
+ assert isinstance(s1, Stream)
459
+ assert isinstance(s2, Stream)
460
+
461
+ # Duplex can be a bit tricky, might as well check it as well
462
+ DUPLEX_TEST_SIZE = 2**20
463
+ CHUNK_SIZE_MAX = 2**14
464
+
465
+ r = random.Random(0)
466
+ i = r.getrandbits(8 * DUPLEX_TEST_SIZE)
467
+ test_data = i.to_bytes(DUPLEX_TEST_SIZE, "little")
468
+
469
+ async def sender(
470
+ s: Stream,
471
+ data: bytes | bytearray | memoryview,
472
+ seed: int,
473
+ ) -> None:
474
+ r = random.Random(seed)
475
+ m = memoryview(data)
476
+ while m:
477
+ chunk_size = r.randint(1, CHUNK_SIZE_MAX)
478
+ await s.send_all(m[:chunk_size])
479
+ m = m[chunk_size:]
480
+
481
+ async def receiver(s: Stream, data: bytes | bytearray, seed: int) -> None:
482
+ r = random.Random(seed)
483
+ got = bytearray()
484
+ while len(got) < len(data):
485
+ chunk = await s.receive_some(r.randint(1, CHUNK_SIZE_MAX))
486
+ assert chunk
487
+ got += chunk
488
+ assert got == data
489
+
490
+ async with _core.open_nursery() as nursery:
491
+ nursery.start_soon(sender, s1, test_data, 0)
492
+ nursery.start_soon(sender, s2, test_data[::-1], 1)
493
+ nursery.start_soon(receiver, s1, test_data[::-1], 2)
494
+ nursery.start_soon(receiver, s2, test_data, 3)
495
+
496
+ async def expect_receive_some_empty() -> None:
497
+ assert await s2.receive_some(10) == b""
498
+ await s2.aclose()
499
+
500
+ async with _core.open_nursery() as nursery:
501
+ nursery.start_soon(expect_receive_some_empty)
502
+ nursery.start_soon(s1.aclose)
503
+
504
+
505
+ async def check_half_closeable_stream(
506
+ stream_maker: StreamMaker[HalfCloseableStream, HalfCloseableStream],
507
+ clogged_stream_maker: StreamMaker[HalfCloseableStream, HalfCloseableStream] | None,
508
+ ) -> None:
509
+ """Perform a number of generic tests on a custom half-closeable stream
510
+ implementation.
511
+
512
+ This is similar to :func:`check_two_way_stream`, except that the maker
513
+ functions are expected to return objects that implement the
514
+ :class:`~trio.abc.HalfCloseableStream` interface.
515
+
516
+ This function tests a *superset* of what :func:`check_two_way_stream`
517
+ checks – if you call this, then you don't need to also call
518
+ :func:`check_two_way_stream`.
519
+
520
+ """
521
+ await check_two_way_stream(stream_maker, clogged_stream_maker)
522
+
523
+ async with _ForceCloseBoth(await stream_maker()) as (s1, s2):
524
+ assert isinstance(s1, HalfCloseableStream)
525
+ assert isinstance(s2, HalfCloseableStream)
526
+
527
+ async def send_x_then_eof(s: HalfCloseableStream) -> None:
528
+ await s.send_all(b"x")
529
+ with assert_checkpoints():
530
+ await s.send_eof()
531
+
532
+ async def expect_x_then_eof(r: HalfCloseableStream) -> None:
533
+ await _core.wait_all_tasks_blocked()
534
+ assert await r.receive_some(10) == b"x"
535
+ assert await r.receive_some(10) == b""
536
+
537
+ async with _core.open_nursery() as nursery:
538
+ nursery.start_soon(send_x_then_eof, s1)
539
+ nursery.start_soon(expect_x_then_eof, s2)
540
+
541
+ # now sending is disallowed
542
+ with _assert_raises(_core.ClosedResourceError):
543
+ await s1.send_all(b"y")
544
+
545
+ # but we can do send_eof again
546
+ with assert_checkpoints():
547
+ await s1.send_eof()
548
+
549
+ # and we can still send stuff back the other way
550
+ async with _core.open_nursery() as nursery:
551
+ nursery.start_soon(send_x_then_eof, s2)
552
+ nursery.start_soon(expect_x_then_eof, s1)
553
+
554
+ if clogged_stream_maker is not None:
555
+ async with _ForceCloseBoth(await clogged_stream_maker()) as (s1, s2):
556
+ # send_all and send_eof simultaneously is not ok
557
+ with _assert_raises(_core.BusyResourceError, wrapped=True):
558
+ async with _core.open_nursery() as nursery:
559
+ nursery.start_soon(s1.send_all, b"x")
560
+ await _core.wait_all_tasks_blocked()
561
+ nursery.start_soon(s1.send_eof)
562
+
563
+ async with _ForceCloseBoth(await clogged_stream_maker()) as (s1, s2):
564
+ # wait_send_all_might_not_block and send_eof simultaneously is not
565
+ # ok either
566
+ with _assert_raises(_core.BusyResourceError, wrapped=True):
567
+ async with _core.open_nursery() as nursery:
568
+ nursery.start_soon(s1.wait_send_all_might_not_block)
569
+ await _core.wait_all_tasks_blocked()
570
+ nursery.start_soon(s1.send_eof)
@@ -0,0 +1,69 @@
1
+ from __future__ import annotations
2
+
3
+ from contextlib import AbstractContextManager, contextmanager
4
+ from typing import TYPE_CHECKING
5
+
6
+ from .. import _core
7
+
8
+ if TYPE_CHECKING:
9
+ from collections.abc import Generator
10
+
11
+
12
+ @contextmanager
13
+ def _assert_yields_or_not(expected: bool) -> Generator[None, None, None]:
14
+ """Check if checkpoints are executed in a block of code."""
15
+ __tracebackhide__ = True
16
+ task = _core.current_task()
17
+ orig_cancel = task._cancel_points
18
+ orig_schedule = task._schedule_points
19
+ try:
20
+ yield
21
+ if expected and (
22
+ task._cancel_points == orig_cancel or task._schedule_points == orig_schedule
23
+ ):
24
+ raise AssertionError("assert_checkpoints block did not yield!")
25
+ finally:
26
+ if not expected and (
27
+ task._cancel_points != orig_cancel or task._schedule_points != orig_schedule
28
+ ):
29
+ raise AssertionError("assert_no_checkpoints block yielded!")
30
+
31
+
32
+ def assert_checkpoints() -> AbstractContextManager[None]:
33
+ """Use as a context manager to check that the code inside the ``with``
34
+ block either exits with an exception or executes at least one
35
+ :ref:`checkpoint <checkpoints>`.
36
+
37
+ Raises:
38
+ AssertionError: if no checkpoint was executed.
39
+
40
+ Example:
41
+ Check that :func:`trio.sleep` is a checkpoint, even if it doesn't
42
+ block::
43
+
44
+ with trio.testing.assert_checkpoints():
45
+ await trio.sleep(0)
46
+
47
+ """
48
+ __tracebackhide__ = True
49
+ return _assert_yields_or_not(True)
50
+
51
+
52
+ def assert_no_checkpoints() -> AbstractContextManager[None]:
53
+ """Use as a context manager to check that the code inside the ``with``
54
+ block does not execute any :ref:`checkpoints <checkpoints>`.
55
+
56
+ Raises:
57
+ AssertionError: if a checkpoint was executed.
58
+
59
+ Example:
60
+ Synchronous code never contains any checkpoints, but we can double-check
61
+ that::
62
+
63
+ send_channel, receive_channel = trio.open_memory_channel(10)
64
+ with trio.testing.assert_no_checkpoints():
65
+ send_channel.send_nowait(None)
66
+
67
+ """
68
+ __tracebackhide__ = True
69
+ return _assert_yields_or_not(False)