@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,317 @@
1
+ import errno
2
+ import re
3
+ import socket
4
+ import sys
5
+
6
+ import pytest
7
+
8
+ import trio
9
+ from trio.testing._fake_net import FakeNet
10
+
11
+ # ENOTCONN gives different messages on different platforms
12
+ if sys.platform == "linux":
13
+ ENOTCONN_MSG = r"^\[Errno 107\] (Transport endpoint is|Socket) not connected$"
14
+ elif sys.platform == "darwin":
15
+ ENOTCONN_MSG = r"^\[Errno 57\] Socket is not connected$"
16
+ else:
17
+ ENOTCONN_MSG = r"^\[Errno 10057\] Unknown error$"
18
+
19
+
20
+ def fn() -> FakeNet:
21
+ fn = FakeNet()
22
+ fn.enable()
23
+ return fn
24
+
25
+
26
+ async def test_basic_udp() -> None:
27
+ fn()
28
+ s1 = trio.socket.socket(type=trio.socket.SOCK_DGRAM)
29
+ s2 = trio.socket.socket(type=trio.socket.SOCK_DGRAM)
30
+
31
+ await s1.bind(("127.0.0.1", 0))
32
+ ip, port = s1.getsockname()
33
+ assert ip == "127.0.0.1"
34
+ assert port != 0
35
+
36
+ with pytest.raises(
37
+ OSError,
38
+ match=r"^\[\w+ \d+\] Invalid argument$",
39
+ ) as exc: # Cannot rebind.
40
+ await s1.bind(("192.0.2.1", 0))
41
+ assert exc.value.errno == errno.EINVAL
42
+
43
+ # Cannot bind multiple sockets to the same address
44
+ with pytest.raises(
45
+ OSError,
46
+ match=r"^\[\w+ \d+\] (Address (already )?in use|Unknown error)$",
47
+ ) as exc:
48
+ await s2.bind(("127.0.0.1", port))
49
+ assert exc.value.errno == errno.EADDRINUSE
50
+
51
+ await s2.sendto(b"xyz", s1.getsockname())
52
+ data, addr = await s1.recvfrom(10)
53
+ assert data == b"xyz"
54
+ assert addr == s2.getsockname()
55
+ await s1.sendto(b"abc", s2.getsockname())
56
+ data, addr = await s2.recvfrom(10)
57
+ assert data == b"abc"
58
+ assert addr == s1.getsockname()
59
+
60
+
61
+ async def test_msg_trunc() -> None:
62
+ fn()
63
+ s1 = trio.socket.socket(type=trio.socket.SOCK_DGRAM)
64
+ s2 = trio.socket.socket(type=trio.socket.SOCK_DGRAM)
65
+ await s1.bind(("127.0.0.1", 0))
66
+ await s2.sendto(b"xyz", s1.getsockname())
67
+ await s1.recvfrom(10)
68
+
69
+
70
+ async def test_recv_methods() -> None:
71
+ """Test all recv methods for codecov"""
72
+ fn()
73
+ s1 = trio.socket.socket(type=trio.socket.SOCK_DGRAM)
74
+ s2 = trio.socket.socket(type=trio.socket.SOCK_DGRAM)
75
+
76
+ # receiving on an unbound socket is a bad idea (I think?)
77
+ with pytest.raises(NotImplementedError, match="code will most likely hang"):
78
+ await s2.recv(10)
79
+
80
+ await s1.bind(("127.0.0.1", 0))
81
+ ip, port = s1.getsockname()
82
+ assert ip == "127.0.0.1"
83
+ assert port != 0
84
+
85
+ # recvfrom
86
+ await s2.sendto(b"abc", s1.getsockname())
87
+ data, addr = await s1.recvfrom(10)
88
+ assert data == b"abc"
89
+ assert addr == s2.getsockname()
90
+
91
+ # recv
92
+ await s1.sendto(b"def", s2.getsockname())
93
+ data = await s2.recv(10)
94
+ assert data == b"def"
95
+
96
+ # recvfrom_into
97
+ assert await s1.sendto(b"ghi", s2.getsockname()) == 3
98
+ buf = bytearray(10)
99
+
100
+ with pytest.raises(NotImplementedError, match=r"^partial recvfrom_into$"):
101
+ nbytes, addr = await s2.recvfrom_into(buf, nbytes=2)
102
+
103
+ nbytes, addr = await s2.recvfrom_into(buf)
104
+ assert nbytes == 3
105
+ assert buf == b"ghi" + b"\x00" * 7
106
+ assert addr == s1.getsockname()
107
+
108
+ # recv_into
109
+ assert await s1.sendto(b"jkl", s2.getsockname()) == 3
110
+ buf2 = bytearray(10)
111
+ nbytes = await s2.recv_into(buf2)
112
+ assert nbytes == 3
113
+ assert buf2 == b"jkl" + b"\x00" * 7
114
+
115
+ if sys.platform == "linux" and sys.implementation.name == "cpython":
116
+ flags: int = socket.MSG_MORE
117
+ else:
118
+ flags = 1
119
+
120
+ # Send seems explicitly non-functional
121
+ with pytest.raises(OSError, match=ENOTCONN_MSG) as exc:
122
+ await s2.send(b"mno")
123
+ assert exc.value.errno == errno.ENOTCONN
124
+ with pytest.raises(
125
+ NotImplementedError, match=r"^FakeNet send flags must be 0, not"
126
+ ):
127
+ await s2.send(b"mno", flags)
128
+
129
+ # sendto errors
130
+ # it's successfully used earlier
131
+ with pytest.raises(
132
+ NotImplementedError, match=r"^FakeNet send flags must be 0, not"
133
+ ):
134
+ await s2.sendto(b"mno", flags, s1.getsockname())
135
+ with pytest.raises(TypeError, match=r"wrong number of arguments$"):
136
+ await s2.sendto(b"mno", flags, s1.getsockname(), "extra arg") # type: ignore[call-overload]
137
+
138
+
139
+ @pytest.mark.skipif(
140
+ sys.platform == "win32",
141
+ reason="functions not in socket on windows",
142
+ )
143
+ async def test_nonwindows_functionality() -> None:
144
+ # mypy doesn't support a good way of aborting typechecking on different platforms
145
+ if sys.platform != "win32": # pragma: no branch
146
+ fn()
147
+ s1 = trio.socket.socket(type=trio.socket.SOCK_DGRAM)
148
+ s2 = trio.socket.socket(type=trio.socket.SOCK_DGRAM)
149
+ await s2.bind(("127.0.0.1", 0))
150
+
151
+ # sendmsg
152
+ with pytest.raises(OSError, match=ENOTCONN_MSG) as exc:
153
+ await s2.sendmsg([b"mno"])
154
+ assert exc.value.errno == errno.ENOTCONN
155
+
156
+ assert await s1.sendmsg([b"jkl"], (), 0, s2.getsockname()) == 3
157
+ data, ancdata, msg_flags, addr = await s2.recvmsg(10)
158
+ assert data == b"jkl"
159
+ assert ancdata == []
160
+ assert msg_flags == 0
161
+ assert addr == s1.getsockname()
162
+
163
+ # TODO: recvmsg
164
+
165
+ # recvmsg_into
166
+ assert await s1.sendto(b"xyzw", s2.getsockname()) == 4
167
+ buf1 = bytearray(2)
168
+ buf2 = bytearray(3)
169
+ ret = await s2.recvmsg_into([buf1, buf2])
170
+ nbytes, ancdata, msg_flags, addr = ret
171
+ assert nbytes == 4
172
+ assert buf1 == b"xy"
173
+ assert buf2 == b"zw" + b"\x00"
174
+ assert ancdata == []
175
+ assert msg_flags == 0
176
+ assert addr == s1.getsockname()
177
+
178
+ # recvmsg_into with MSG_TRUNC set
179
+ assert await s1.sendto(b"xyzwv", s2.getsockname()) == 5
180
+ buf1 = bytearray(2)
181
+ ret = await s2.recvmsg_into([buf1])
182
+ nbytes, ancdata, msg_flags, addr = ret
183
+ assert nbytes == 2
184
+ assert buf1 == b"xy"
185
+ assert ancdata == []
186
+ assert msg_flags == socket.MSG_TRUNC
187
+ assert addr == s1.getsockname()
188
+
189
+ with pytest.raises(
190
+ AttributeError,
191
+ match=r"^'FakeSocket' object has no attribute 'share'$",
192
+ ):
193
+ await s1.share(0) # type: ignore[attr-defined]
194
+
195
+
196
+ @pytest.mark.skipif(
197
+ sys.platform != "win32",
198
+ reason="windows-specific fakesocket testing",
199
+ )
200
+ async def test_windows_functionality() -> None:
201
+ # mypy doesn't support a good way of aborting typechecking on different platforms
202
+ if sys.platform == "win32": # pragma: no branch
203
+ fn()
204
+ s1 = trio.socket.socket(type=trio.socket.SOCK_DGRAM)
205
+ s2 = trio.socket.socket(type=trio.socket.SOCK_DGRAM)
206
+ await s1.bind(("127.0.0.1", 0))
207
+ with pytest.raises(
208
+ AttributeError,
209
+ match=r"^'FakeSocket' object has no attribute 'sendmsg'$",
210
+ ):
211
+ await s1.sendmsg([b"jkl"], (), 0, s2.getsockname()) # type: ignore[attr-defined]
212
+ with pytest.raises(
213
+ AttributeError,
214
+ match=r"^'FakeSocket' object has no attribute 'recvmsg'$",
215
+ ):
216
+ s2.recvmsg(0) # type: ignore[attr-defined]
217
+ with pytest.raises(
218
+ AttributeError,
219
+ match=r"^'FakeSocket' object has no attribute 'recvmsg_into'$",
220
+ ):
221
+ s2.recvmsg_into([]) # type: ignore[attr-defined]
222
+ with pytest.raises(NotImplementedError):
223
+ s1.share(0)
224
+
225
+
226
+ async def test_basic_tcp() -> None:
227
+ fn()
228
+ with pytest.raises(NotImplementedError):
229
+ trio.socket.socket()
230
+
231
+
232
+ async def test_not_implemented_functions() -> None:
233
+ fn()
234
+ s1 = trio.socket.socket(type=trio.socket.SOCK_DGRAM)
235
+
236
+ # getsockopt
237
+ with pytest.raises(
238
+ OSError,
239
+ match=r"^FakeNet doesn't implement getsockopt\(\d, \d\)$",
240
+ ):
241
+ s1.getsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY)
242
+
243
+ # setsockopt
244
+ with pytest.raises(
245
+ NotImplementedError,
246
+ match=r"^FakeNet always has IPV6_V6ONLY=True$",
247
+ ):
248
+ s1.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, False)
249
+ with pytest.raises(
250
+ OSError,
251
+ match=r"^FakeNet doesn't implement setsockopt\(\d+, \d+, \.\.\.\)$",
252
+ ):
253
+ s1.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, True)
254
+ with pytest.raises(
255
+ OSError,
256
+ match=r"^FakeNet doesn't implement setsockopt\(\d+, \d+, \.\.\.\)$",
257
+ ):
258
+ s1.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
259
+
260
+ # set_inheritable
261
+ s1.set_inheritable(False)
262
+ with pytest.raises(
263
+ NotImplementedError,
264
+ match=r"^FakeNet can't make inheritable sockets$",
265
+ ):
266
+ s1.set_inheritable(True)
267
+
268
+ # get_inheritable
269
+ assert not s1.get_inheritable()
270
+
271
+
272
+ async def test_getpeername() -> None:
273
+ fn()
274
+ s1 = trio.socket.socket(type=trio.socket.SOCK_DGRAM)
275
+ with pytest.raises(OSError, match=ENOTCONN_MSG) as exc:
276
+ s1.getpeername()
277
+ assert exc.value.errno == errno.ENOTCONN
278
+
279
+ await s1.bind(("127.0.0.1", 0))
280
+
281
+ with pytest.raises(
282
+ AssertionError,
283
+ match=r"^This method seems to assume that self._binding has a remote UDPEndpoint$",
284
+ ):
285
+ s1.getpeername()
286
+
287
+
288
+ async def test_init() -> None:
289
+ fn()
290
+ with pytest.raises(
291
+ NotImplementedError,
292
+ match=re.escape(
293
+ f"FakeNet doesn't (yet) support type={trio.socket.SOCK_STREAM}",
294
+ ),
295
+ ):
296
+ s1 = trio.socket.socket()
297
+
298
+ # getsockname on unbound ipv4 socket
299
+ s1 = trio.socket.socket(type=trio.socket.SOCK_DGRAM)
300
+ assert s1.getsockname() == ("0.0.0.0", 0)
301
+
302
+ # getsockname on bound ipv4 socket
303
+ await s1.bind(("0.0.0.0", 0))
304
+ ip, port = s1.getsockname()
305
+ assert ip == "127.0.0.1"
306
+ assert port != 0
307
+
308
+ # getsockname on unbound ipv6 socket
309
+ s2 = trio.socket.socket(family=socket.AF_INET6, type=socket.SOCK_DGRAM)
310
+ assert s2.getsockname() == ("::", 0)
311
+
312
+ # getsockname on bound ipv6 socket
313
+ await s2.bind(("::", 0))
314
+ ip, port, *_ = s2.getsockname()
315
+ assert ip == "::1"
316
+ assert port != 0
317
+ assert _ == [0, 0]
@@ -0,0 +1,269 @@
1
+ from __future__ import annotations
2
+
3
+ import importlib
4
+ import io
5
+ import os
6
+ import re
7
+ from typing import TYPE_CHECKING
8
+ from unittest import mock
9
+ from unittest.mock import sentinel
10
+
11
+ import pytest
12
+
13
+ import trio
14
+ from trio import _core, _file_io
15
+ from trio._file_io import _FILE_ASYNC_METHODS, _FILE_SYNC_ATTRS, AsyncIOWrapper
16
+
17
+ if TYPE_CHECKING:
18
+ import pathlib
19
+
20
+
21
+ @pytest.fixture
22
+ def path(tmp_path: pathlib.Path) -> str:
23
+ return os.fspath(tmp_path / "test")
24
+
25
+
26
+ @pytest.fixture
27
+ def wrapped() -> mock.Mock:
28
+ return mock.Mock(spec_set=io.StringIO)
29
+
30
+
31
+ @pytest.fixture
32
+ def async_file(wrapped: mock.Mock) -> AsyncIOWrapper[mock.Mock]:
33
+ return trio.wrap_file(wrapped)
34
+
35
+
36
+ def test_wrap_invalid() -> None:
37
+ with pytest.raises(TypeError):
38
+ trio.wrap_file("")
39
+
40
+
41
+ def test_wrap_non_iobase() -> None:
42
+ class FakeFile:
43
+ def close(self) -> None: # pragma: no cover
44
+ pass
45
+
46
+ def write(self) -> None: # pragma: no cover
47
+ pass
48
+
49
+ wrapped = FakeFile()
50
+ assert not isinstance(wrapped, io.IOBase)
51
+
52
+ async_file = trio.wrap_file(wrapped)
53
+ assert isinstance(async_file, AsyncIOWrapper)
54
+
55
+ del FakeFile.write
56
+
57
+ with pytest.raises(TypeError):
58
+ trio.wrap_file(FakeFile())
59
+
60
+
61
+ def test_wrapped_property(
62
+ async_file: AsyncIOWrapper[mock.Mock],
63
+ wrapped: mock.Mock,
64
+ ) -> None:
65
+ assert async_file.wrapped is wrapped
66
+
67
+
68
+ def test_dir_matches_wrapped(
69
+ async_file: AsyncIOWrapper[mock.Mock],
70
+ wrapped: mock.Mock,
71
+ ) -> None:
72
+ attrs = _FILE_SYNC_ATTRS.union(_FILE_ASYNC_METHODS)
73
+
74
+ # all supported attrs in wrapped should be available in async_file
75
+ assert all(attr in dir(async_file) for attr in attrs if attr in dir(wrapped))
76
+ # all supported attrs not in wrapped should not be available in async_file
77
+ assert not any(
78
+ attr in dir(async_file) for attr in attrs if attr not in dir(wrapped)
79
+ )
80
+
81
+
82
+ def test_unsupported_not_forwarded() -> None:
83
+ class FakeFile(io.RawIOBase):
84
+ def unsupported_attr(self) -> None: # pragma: no cover
85
+ pass
86
+
87
+ async_file = trio.wrap_file(FakeFile())
88
+
89
+ assert hasattr(async_file.wrapped, "unsupported_attr")
90
+
91
+ with pytest.raises(AttributeError):
92
+ # B018 "useless expression"
93
+ async_file.unsupported_attr # type: ignore[attr-defined] # noqa: B018
94
+
95
+
96
+ def test_type_stubs_match_lists() -> None:
97
+ """Check the manual stubs match the list of wrapped methods."""
98
+ # Fetch the module's source code.
99
+ assert _file_io.__spec__ is not None
100
+ loader = _file_io.__spec__.loader
101
+ assert isinstance(loader, importlib.abc.SourceLoader)
102
+ source = io.StringIO(loader.get_source("trio._file_io"))
103
+
104
+ # Find the class, then find the TYPE_CHECKING block.
105
+ for line in source:
106
+ if "class AsyncIOWrapper" in line:
107
+ break
108
+ else: # pragma: no cover - should always find this
109
+ pytest.fail("No class definition line?")
110
+
111
+ for line in source:
112
+ if "if TYPE_CHECKING" in line:
113
+ break
114
+ else: # pragma: no cover - should always find this
115
+ pytest.fail("No TYPE CHECKING line?")
116
+
117
+ # Now we should be at the type checking block.
118
+ found: list[tuple[str, str]] = []
119
+ for line in source: # pragma: no branch - expected to break early
120
+ if line.strip() and not line.startswith(" " * 8):
121
+ break # Dedented out of the if TYPE_CHECKING block.
122
+ match = re.match(r"\s*(async )?def ([a-zA-Z0-9_]+)\(", line)
123
+ if match is not None:
124
+ kind = "async" if match.group(1) is not None else "sync"
125
+ found.append((match.group(2), kind))
126
+
127
+ # Compare two lists so that we can easily see duplicates, and see what is different overall.
128
+ expected = [(fname, "async") for fname in _FILE_ASYNC_METHODS]
129
+ expected += [(fname, "sync") for fname in _FILE_SYNC_ATTRS]
130
+ # Ignore order, error if duplicates are present.
131
+ found.sort()
132
+ expected.sort()
133
+ assert found == expected
134
+
135
+
136
+ def test_sync_attrs_forwarded(
137
+ async_file: AsyncIOWrapper[mock.Mock],
138
+ wrapped: mock.Mock,
139
+ ) -> None:
140
+ for attr_name in _FILE_SYNC_ATTRS:
141
+ if attr_name not in dir(async_file):
142
+ continue
143
+
144
+ assert getattr(async_file, attr_name) is getattr(wrapped, attr_name)
145
+
146
+
147
+ def test_sync_attrs_match_wrapper(
148
+ async_file: AsyncIOWrapper[mock.Mock],
149
+ wrapped: mock.Mock,
150
+ ) -> None:
151
+ for attr_name in _FILE_SYNC_ATTRS:
152
+ if attr_name in dir(async_file):
153
+ continue
154
+
155
+ with pytest.raises(AttributeError):
156
+ getattr(async_file, attr_name)
157
+
158
+ with pytest.raises(AttributeError):
159
+ getattr(wrapped, attr_name)
160
+
161
+
162
+ def test_async_methods_generated_once(async_file: AsyncIOWrapper[mock.Mock]) -> None:
163
+ for meth_name in _FILE_ASYNC_METHODS:
164
+ if meth_name not in dir(async_file):
165
+ continue
166
+
167
+ assert getattr(async_file, meth_name) is getattr(async_file, meth_name)
168
+
169
+
170
+ # I gave up on typing this one
171
+ def test_async_methods_signature(async_file: AsyncIOWrapper[mock.Mock]) -> None:
172
+ # use read as a representative of all async methods
173
+ assert async_file.read.__name__ == "read"
174
+ assert async_file.read.__qualname__ == "AsyncIOWrapper.read"
175
+
176
+ assert async_file.read.__doc__ is not None
177
+ assert "io.StringIO.read" in async_file.read.__doc__
178
+
179
+
180
+ async def test_async_methods_wrap(
181
+ async_file: AsyncIOWrapper[mock.Mock],
182
+ wrapped: mock.Mock,
183
+ ) -> None:
184
+ for meth_name in _FILE_ASYNC_METHODS:
185
+ if meth_name not in dir(async_file):
186
+ continue
187
+
188
+ meth = getattr(async_file, meth_name)
189
+ wrapped_meth = getattr(wrapped, meth_name)
190
+
191
+ value = await meth(sentinel.argument, keyword=sentinel.keyword)
192
+
193
+ wrapped_meth.assert_called_once_with(
194
+ sentinel.argument,
195
+ keyword=sentinel.keyword,
196
+ )
197
+ assert value == wrapped_meth()
198
+
199
+ wrapped.reset_mock()
200
+
201
+
202
+ def test_async_methods_match_wrapper(
203
+ async_file: AsyncIOWrapper[mock.Mock],
204
+ wrapped: mock.Mock,
205
+ ) -> None:
206
+ for meth_name in _FILE_ASYNC_METHODS:
207
+ if meth_name in dir(async_file):
208
+ continue
209
+
210
+ with pytest.raises(AttributeError):
211
+ getattr(async_file, meth_name)
212
+
213
+ with pytest.raises(AttributeError):
214
+ getattr(wrapped, meth_name)
215
+
216
+
217
+ async def test_open(path: pathlib.Path) -> None:
218
+ f = await trio.open_file(path, "w")
219
+
220
+ assert isinstance(f, AsyncIOWrapper)
221
+
222
+ await f.aclose()
223
+
224
+
225
+ async def test_open_context_manager(path: pathlib.Path) -> None:
226
+ async with await trio.open_file(path, "w") as f:
227
+ assert isinstance(f, AsyncIOWrapper)
228
+ assert not f.closed
229
+
230
+ assert f.closed
231
+
232
+
233
+ async def test_async_iter() -> None:
234
+ async_file = trio.wrap_file(io.StringIO("test\nfoo\nbar"))
235
+ expected = list(async_file.wrapped)
236
+ async_file.wrapped.seek(0)
237
+
238
+ result = [line async for line in async_file]
239
+
240
+ assert result == expected
241
+
242
+
243
+ async def test_aclose_cancelled(path: pathlib.Path) -> None:
244
+ with _core.CancelScope() as cscope:
245
+ f = await trio.open_file(path, "w")
246
+ cscope.cancel()
247
+
248
+ with pytest.raises(_core.Cancelled):
249
+ await f.write("a")
250
+
251
+ with pytest.raises(_core.Cancelled):
252
+ await f.aclose()
253
+
254
+ assert f.closed
255
+
256
+
257
+ async def test_detach_rewraps_asynciobase(tmp_path: pathlib.Path) -> None:
258
+ tmp_file = tmp_path / "filename"
259
+ tmp_file.touch()
260
+ # flake8-async does not like opening files in async mode
261
+ with open(tmp_file, mode="rb", buffering=0) as raw: # noqa: ASYNC230
262
+ buffered = io.BufferedReader(raw)
263
+
264
+ async_file = trio.wrap_file(buffered)
265
+
266
+ detached = await async_file.detach()
267
+
268
+ assert isinstance(detached, AsyncIOWrapper)
269
+ assert detached.wrapped is raw
@@ -0,0 +1,98 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import NoReturn
4
+
5
+ import attrs
6
+ import pytest
7
+
8
+ from .._highlevel_generic import StapledStream
9
+ from ..abc import ReceiveStream, SendStream
10
+
11
+
12
+ @attrs.define(slots=False)
13
+ class RecordSendStream(SendStream):
14
+ record: list[str | tuple[str, object]] = attrs.Factory(list)
15
+
16
+ async def send_all(self, data: object) -> None:
17
+ self.record.append(("send_all", data))
18
+
19
+ async def wait_send_all_might_not_block(self) -> None:
20
+ self.record.append("wait_send_all_might_not_block")
21
+
22
+ async def aclose(self) -> None:
23
+ self.record.append("aclose")
24
+
25
+
26
+ @attrs.define(slots=False)
27
+ class RecordReceiveStream(ReceiveStream):
28
+ record: list[str | tuple[str, int | None]] = attrs.Factory(list)
29
+
30
+ async def receive_some(self, max_bytes: int | None = None) -> bytes:
31
+ self.record.append(("receive_some", max_bytes))
32
+ return b""
33
+
34
+ async def aclose(self) -> None:
35
+ self.record.append("aclose")
36
+
37
+
38
+ async def test_StapledStream() -> None:
39
+ send_stream = RecordSendStream()
40
+ receive_stream = RecordReceiveStream()
41
+ stapled = StapledStream(send_stream, receive_stream)
42
+
43
+ assert stapled.send_stream is send_stream
44
+ assert stapled.receive_stream is receive_stream
45
+
46
+ await stapled.send_all(b"foo")
47
+ await stapled.wait_send_all_might_not_block()
48
+ assert send_stream.record == [
49
+ ("send_all", b"foo"),
50
+ "wait_send_all_might_not_block",
51
+ ]
52
+ send_stream.record.clear()
53
+
54
+ await stapled.send_eof()
55
+ assert send_stream.record == ["aclose"]
56
+ send_stream.record.clear()
57
+
58
+ async def fake_send_eof() -> None:
59
+ send_stream.record.append("send_eof")
60
+
61
+ send_stream.send_eof = fake_send_eof # type: ignore[attr-defined]
62
+ await stapled.send_eof()
63
+ assert send_stream.record == ["send_eof"]
64
+
65
+ send_stream.record.clear()
66
+ assert receive_stream.record == []
67
+
68
+ await stapled.receive_some(1234)
69
+ assert receive_stream.record == [("receive_some", 1234)]
70
+ assert send_stream.record == []
71
+ receive_stream.record.clear()
72
+
73
+ await stapled.aclose()
74
+ assert receive_stream.record == ["aclose"]
75
+ assert send_stream.record == ["aclose"]
76
+
77
+
78
+ async def test_StapledStream_with_erroring_close() -> None:
79
+ # Make sure that if one of the aclose methods errors out, then the other
80
+ # one still gets called.
81
+ class BrokenSendStream(RecordSendStream):
82
+ async def aclose(self) -> NoReturn:
83
+ await super().aclose()
84
+ raise ValueError("send error")
85
+
86
+ class BrokenReceiveStream(RecordReceiveStream):
87
+ async def aclose(self) -> NoReturn:
88
+ await super().aclose()
89
+ raise ValueError("recv error")
90
+
91
+ stapled = StapledStream(BrokenSendStream(), BrokenReceiveStream())
92
+
93
+ with pytest.raises(ValueError, match=r"^(send|recv) error$") as excinfo:
94
+ await stapled.aclose()
95
+ assert isinstance(excinfo.value.__context__, ValueError)
96
+
97
+ assert stapled.send_stream.record == ["aclose"]
98
+ assert stapled.receive_stream.record == ["aclose"]