@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,197 @@
1
+ from __future__ import annotations
2
+
3
+ import math
4
+ import sys
5
+ from contextlib import contextmanager
6
+ from typing import TYPE_CHECKING, NoReturn
7
+
8
+ import trio
9
+
10
+ if TYPE_CHECKING:
11
+ from collections.abc import Generator
12
+
13
+
14
+ def move_on_at(deadline: float, *, shield: bool = False) -> trio.CancelScope:
15
+ """Use as a context manager to create a cancel scope with the given
16
+ absolute deadline.
17
+
18
+ Args:
19
+ deadline (float): The deadline.
20
+ shield (bool): Initial value for the `~trio.CancelScope.shield` attribute
21
+ of the newly created cancel scope.
22
+
23
+ Raises:
24
+ ValueError: if deadline is NaN.
25
+
26
+ """
27
+ # CancelScope validates that deadline isn't math.nan
28
+ return trio.CancelScope(deadline=deadline, shield=shield)
29
+
30
+
31
+ def move_on_after(
32
+ seconds: float,
33
+ *,
34
+ shield: bool = False,
35
+ ) -> trio.CancelScope:
36
+ """Use as a context manager to create a cancel scope whose deadline is
37
+ set to now + *seconds*.
38
+
39
+ The deadline of the cancel scope is calculated upon entering.
40
+
41
+ Args:
42
+ seconds (float): The timeout.
43
+ shield (bool): Initial value for the `~trio.CancelScope.shield` attribute
44
+ of the newly created cancel scope.
45
+
46
+ Raises:
47
+ ValueError: if ``seconds`` is less than zero or NaN.
48
+
49
+ """
50
+ # duplicate validation logic to have the correct parameter name
51
+ if seconds < 0:
52
+ raise ValueError("`seconds` must be non-negative")
53
+ if math.isnan(seconds):
54
+ raise ValueError("`seconds` must not be NaN")
55
+ return trio.CancelScope(
56
+ shield=shield,
57
+ relative_deadline=seconds,
58
+ )
59
+
60
+
61
+ async def sleep_forever() -> NoReturn:
62
+ """Pause execution of the current task forever (or until cancelled).
63
+
64
+ Equivalent to calling ``await sleep(math.inf)``, except that if manually
65
+ rescheduled this will raise a `RuntimeError`.
66
+
67
+ Raises:
68
+ RuntimeError: if rescheduled
69
+
70
+ """
71
+ await trio.lowlevel.wait_task_rescheduled(lambda _: trio.lowlevel.Abort.SUCCEEDED)
72
+ raise RuntimeError("Should never have been rescheduled!")
73
+
74
+
75
+ async def sleep_until(deadline: float) -> None:
76
+ """Pause execution of the current task until the given time.
77
+
78
+ The difference between :func:`sleep` and :func:`sleep_until` is that the
79
+ former takes a relative time and the latter takes an absolute time
80
+ according to Trio's internal clock (as returned by :func:`current_time`).
81
+
82
+ Args:
83
+ deadline (float): The time at which we should wake up again. May be in
84
+ the past, in which case this function executes a checkpoint but
85
+ does not block.
86
+
87
+ Raises:
88
+ ValueError: if deadline is NaN.
89
+
90
+ """
91
+ with move_on_at(deadline):
92
+ await sleep_forever()
93
+
94
+
95
+ async def sleep(seconds: float) -> None:
96
+ """Pause execution of the current task for the given number of seconds.
97
+
98
+ Args:
99
+ seconds (float): The number of seconds to sleep. May be zero to
100
+ insert a checkpoint without actually blocking.
101
+
102
+ Raises:
103
+ ValueError: if *seconds* is negative or NaN.
104
+
105
+ """
106
+ if seconds < 0:
107
+ raise ValueError("`seconds` must be non-negative")
108
+ if seconds == 0:
109
+ await trio.lowlevel.checkpoint()
110
+ else:
111
+ await sleep_until(trio.current_time() + seconds)
112
+
113
+
114
+ class TooSlowError(Exception):
115
+ """Raised by :func:`fail_after` and :func:`fail_at` if the timeout
116
+ expires.
117
+
118
+ """
119
+
120
+
121
+ @contextmanager
122
+ def fail_at(
123
+ deadline: float,
124
+ *,
125
+ shield: bool = False,
126
+ ) -> Generator[trio.CancelScope, None, None]:
127
+ """Creates a cancel scope with the given deadline, and raises an error if it
128
+ is actually cancelled.
129
+
130
+ This function and :func:`move_on_at` are similar in that both create a
131
+ cancel scope with a given absolute deadline, and if the deadline expires
132
+ then both will cause :exc:`Cancelled` to be raised within the scope. The
133
+ difference is that when the :exc:`Cancelled` exception reaches
134
+ :func:`move_on_at`, it's caught and discarded. When it reaches
135
+ :func:`fail_at`, then it's caught and :exc:`TooSlowError` is raised in its
136
+ place.
137
+
138
+ Args:
139
+ deadline (float): The deadline.
140
+ shield (bool): Initial value for the `~trio.CancelScope.shield` attribute
141
+ of the newly created cancel scope.
142
+
143
+ Raises:
144
+ TooSlowError: if a :exc:`Cancelled` exception is raised in this scope
145
+ and caught by the context manager.
146
+ ValueError: if deadline is NaN.
147
+
148
+ """
149
+ with move_on_at(deadline, shield=shield) as scope:
150
+ yield scope
151
+ if scope.cancelled_caught:
152
+ raise TooSlowError
153
+
154
+
155
+ @contextmanager
156
+ def fail_after(
157
+ seconds: float,
158
+ *,
159
+ shield: bool = False,
160
+ ) -> Generator[trio.CancelScope, None, None]:
161
+ """Creates a cancel scope with the given timeout, and raises an error if
162
+ it is actually cancelled.
163
+
164
+ This function and :func:`move_on_after` are similar in that both create a
165
+ cancel scope with a given timeout, and if the timeout expires then both
166
+ will cause :exc:`Cancelled` to be raised within the scope. The difference
167
+ is that when the :exc:`Cancelled` exception reaches :func:`move_on_after`,
168
+ it's caught and discarded. When it reaches :func:`fail_after`, then it's
169
+ caught and :exc:`TooSlowError` is raised in its place.
170
+
171
+ The deadline of the cancel scope is calculated upon entering.
172
+
173
+ Args:
174
+ seconds (float): The timeout.
175
+ shield (bool): Initial value for the `~trio.CancelScope.shield` attribute
176
+ of the newly created cancel scope.
177
+
178
+ Raises:
179
+ TooSlowError: if a :exc:`Cancelled` exception is raised in this scope
180
+ and caught by the context manager.
181
+ ValueError: if *seconds* is less than zero or NaN.
182
+
183
+ """
184
+ with move_on_after(seconds, shield=shield) as scope:
185
+ yield scope
186
+ if scope.cancelled_caught:
187
+ raise TooSlowError
188
+
189
+
190
+ # Users don't need to know that fail_at & fail_after wraps move_on_at and move_on_after
191
+ # and there is no functional difference. So we replace the return value when generating
192
+ # documentation.
193
+ if "sphinx.ext.autodoc" in sys.modules:
194
+ import inspect
195
+
196
+ for c in (fail_at, fail_after):
197
+ c.__signature__ = inspect.Signature.from_callable(c).replace(return_annotation=trio.CancelScope) # type: ignore[union-attr]
File without changes
@@ -0,0 +1,401 @@
1
+ #! /usr/bin/env python3
2
+ """
3
+ Code generation script for class methods
4
+ to be exported as public API
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ import argparse
10
+ import ast
11
+ import os
12
+ import subprocess
13
+ import sys
14
+ from pathlib import Path
15
+ from textwrap import indent
16
+ from typing import TYPE_CHECKING, TypeGuard
17
+
18
+ import attrs
19
+
20
+ if TYPE_CHECKING:
21
+ from collections.abc import Iterable, Iterator
22
+
23
+ # keep these imports up to date with conditional imports in test_gen_exports
24
+ # isort: split
25
+ import astor
26
+
27
+ PREFIX = "_generated"
28
+
29
+ HEADER = """# ***********************************************************
30
+ # ******* WARNING: AUTOGENERATED! ALL EDITS WILL BE LOST ******
31
+ # *************************************************************
32
+ from __future__ import annotations
33
+
34
+ import sys
35
+
36
+ from ._ki import enable_ki_protection
37
+ from ._run import GLOBAL_RUN_CONTEXT
38
+ """
39
+
40
+ TEMPLATE = """try:
41
+ return{}GLOBAL_RUN_CONTEXT.{}.{}
42
+ except AttributeError:
43
+ raise RuntimeError("must be called from async context") from None
44
+ """
45
+
46
+
47
+ @attrs.define
48
+ class File:
49
+ path: Path
50
+ modname: str
51
+ platform: str = attrs.field(default="", kw_only=True)
52
+ imports: str = attrs.field(default="", kw_only=True)
53
+
54
+
55
+ def is_function(node: ast.AST) -> TypeGuard[ast.FunctionDef | ast.AsyncFunctionDef]:
56
+ """Check if the AST node is either a function
57
+ or an async function
58
+ """
59
+ return isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef))
60
+
61
+
62
+ def is_public(node: ast.AST) -> TypeGuard[ast.FunctionDef | ast.AsyncFunctionDef]:
63
+ """Check if the AST node has a _public decorator"""
64
+ if is_function(node):
65
+ for decorator in node.decorator_list:
66
+ if isinstance(decorator, ast.Name) and decorator.id == "_public":
67
+ return True
68
+ return False
69
+
70
+
71
+ def get_public_methods(
72
+ tree: ast.AST,
73
+ ) -> Iterator[ast.FunctionDef | ast.AsyncFunctionDef]:
74
+ """Return a list of methods marked as public.
75
+ The function walks the given tree and extracts
76
+ all objects that are functions which are marked
77
+ public.
78
+ """
79
+ for node in ast.walk(tree):
80
+ if is_public(node):
81
+ yield node
82
+
83
+
84
+ def create_passthrough_args(funcdef: ast.FunctionDef | ast.AsyncFunctionDef) -> str:
85
+ """Given a function definition, create a string that represents taking all
86
+ the arguments from the function, and passing them through to another
87
+ invocation of the same function.
88
+
89
+ Example input: ast.parse("def f(a, *, b): ...")
90
+ Example output: "(a, b=b)"
91
+ """
92
+ call_args = [arg.arg for arg in funcdef.args.args]
93
+ if funcdef.args.vararg:
94
+ call_args.append("*" + funcdef.args.vararg.arg)
95
+ for arg in funcdef.args.kwonlyargs:
96
+ call_args.append(arg.arg + "=" + arg.arg) # noqa: PERF401 # clarity
97
+ if funcdef.args.kwarg:
98
+ call_args.append("**" + funcdef.args.kwarg.arg)
99
+ return "({})".format(", ".join(call_args))
100
+
101
+
102
+ def run_black(file: File, source: str) -> tuple[bool, str]:
103
+ """Run black on the specified file.
104
+
105
+ Returns:
106
+ Tuple of success and result string.
107
+ ex.:
108
+ (False, "Failed to run black!\nerror: cannot format ...")
109
+ (True, "<formatted source>")
110
+
111
+ Raises:
112
+ ImportError: If black is not installed.
113
+ """
114
+ # imported to check that `subprocess` calls will succeed
115
+ import black # noqa: F401
116
+
117
+ # Black has an undocumented API, but it doesn't easily allow reading configuration from
118
+ # pyproject.toml, and simultaneously pass in / receive the code as a string.
119
+ # https://github.com/psf/black/issues/779
120
+ result = subprocess.run(
121
+ # "-" as a filename = use stdin, return on stdout.
122
+ [sys.executable, "-m", "black", "--stdin-filename", file.path, "-"],
123
+ input=source,
124
+ capture_output=True,
125
+ encoding="utf8",
126
+ )
127
+
128
+ if result.returncode != 0:
129
+ return False, f"Failed to run black!\n{result.stderr}"
130
+ return True, result.stdout
131
+
132
+
133
+ def run_ruff(file: File, source: str) -> tuple[bool, str]:
134
+ """Run ruff on the specified file.
135
+
136
+ Returns:
137
+ Tuple of success and result string.
138
+ ex.:
139
+ (False, "Failed to run ruff!\nerror: Failed to parse ...")
140
+ (True, "<formatted source>")
141
+
142
+ Raises:
143
+ ImportError: If ruff is not installed.
144
+ """
145
+ # imported to check that `subprocess` calls will succeed
146
+ import ruff # noqa: F401
147
+
148
+ result = subprocess.run(
149
+ # "-" as a filename = use stdin, return on stdout.
150
+ [
151
+ sys.executable,
152
+ "-m",
153
+ "ruff",
154
+ "check",
155
+ "--fix",
156
+ "--unsafe-fixes",
157
+ "--stdin-filename",
158
+ file.path,
159
+ "-",
160
+ ],
161
+ input=source,
162
+ capture_output=True,
163
+ encoding="utf8",
164
+ )
165
+
166
+ if result.returncode != 0:
167
+ return False, f"Failed to run ruff!\n{result.stderr}"
168
+ return True, result.stdout
169
+
170
+
171
+ def run_linters(file: File, source: str) -> str:
172
+ """Format the specified file using black and ruff.
173
+
174
+ Returns:
175
+ Formatted source code.
176
+
177
+ Raises:
178
+ ImportError: If either is not installed.
179
+ SystemExit: If either failed.
180
+ """
181
+
182
+ for fn in (run_black, run_ruff):
183
+ success, source = fn(file, source)
184
+ if not success:
185
+ print(source)
186
+ sys.exit(1)
187
+
188
+ return source
189
+
190
+
191
+ def gen_public_wrappers_source(file: File) -> str:
192
+ """Scan the given .py file for @_public decorators, and generate wrapper
193
+ functions.
194
+
195
+ """
196
+ header = [HEADER]
197
+ header.append(file.imports)
198
+ if file.platform:
199
+ # Simple checks to avoid repeating imports. If this messes up, type checkers/tests will
200
+ # just give errors.
201
+ if "TYPE_CHECKING" not in file.imports:
202
+ header.append("from typing import TYPE_CHECKING\n")
203
+ if "import sys" not in file.imports: # pragma: no cover
204
+ header.append("import sys\n")
205
+ header.append(
206
+ f'\nassert not TYPE_CHECKING or sys.platform=="{file.platform}"\n',
207
+ )
208
+
209
+ generated = ["".join(header)]
210
+
211
+ source = astor.code_to_ast.parse_file(file.path)
212
+ method_names = []
213
+ for method in get_public_methods(source):
214
+ # Remove self from arguments
215
+ assert method.args.args[0].arg == "self"
216
+ del method.args.args[0]
217
+ method_names.append(method.name)
218
+
219
+ for dec in method.decorator_list: # pragma: no cover
220
+ if isinstance(dec, ast.Name) and dec.id == "contextmanager":
221
+ is_cm = True
222
+ break
223
+ else:
224
+ is_cm = False
225
+
226
+ # Remove decorators
227
+ method.decorator_list = [ast.Name("enable_ki_protection")]
228
+
229
+ # Create pass through arguments
230
+ new_args = create_passthrough_args(method)
231
+
232
+ # Remove method body without the docstring
233
+ if ast.get_docstring(method) is None:
234
+ del method.body[:]
235
+ else:
236
+ # The first entry is always the docstring
237
+ del method.body[1:]
238
+
239
+ # Create the function definition including the body
240
+ func = astor.to_source(method, indent_with=" " * 4)
241
+
242
+ if is_cm: # pragma: no cover
243
+ func = func.replace("->Iterator", "->AbstractContextManager")
244
+
245
+ # Create export function body
246
+ template = TEMPLATE.format(
247
+ " await " if isinstance(method, ast.AsyncFunctionDef) else " ",
248
+ file.modname,
249
+ method.name + new_args,
250
+ )
251
+
252
+ # Assemble function definition arguments and body
253
+ snippet = func + indent(template, " " * 4)
254
+
255
+ # Append the snippet to the corresponding module
256
+ generated.append(snippet)
257
+
258
+ method_names.sort()
259
+ # Insert after the header, before function definitions
260
+ generated.insert(1, f"__all__ = {method_names!r}")
261
+ return "\n\n".join(generated)
262
+
263
+
264
+ def matches_disk_files(new_files: dict[str, str]) -> bool:
265
+ for new_path, new_source in new_files.items():
266
+ if not os.path.exists(new_path):
267
+ return False
268
+ old_source = Path(new_path).read_text(encoding="utf-8")
269
+ if old_source != new_source:
270
+ return False
271
+ return True
272
+
273
+
274
+ def process(files: Iterable[File], *, do_test: bool) -> None:
275
+ new_files = {}
276
+ for file in files:
277
+ print("Scanning:", file.path)
278
+ new_source = gen_public_wrappers_source(file)
279
+ new_source = run_linters(file, new_source)
280
+ dirname, basename = os.path.split(file.path)
281
+ new_path = os.path.join(dirname, PREFIX + basename)
282
+ new_files[new_path] = new_source
283
+ matches_disk = matches_disk_files(new_files)
284
+ if do_test:
285
+ if not matches_disk:
286
+ print("Generated sources are outdated. Please regenerate.")
287
+ sys.exit(1)
288
+ else:
289
+ print("Generated sources are up to date.")
290
+ else:
291
+ for new_path, new_source in new_files.items():
292
+ Path(new_path).write_text(new_source, encoding="utf-8", newline="\n")
293
+ print("Regenerated sources successfully.")
294
+ if not matches_disk: # TODO: test this branch
295
+ # With pre-commit integration, show that we edited files.
296
+ sys.exit(1)
297
+
298
+
299
+ # This is in fact run in CI, but only in the formatting check job, which
300
+ # doesn't collect coverage.
301
+ def main() -> None: # pragma: no cover
302
+ parser = argparse.ArgumentParser(
303
+ description="Generate python code for public api wrappers",
304
+ )
305
+ parser.add_argument(
306
+ "--test",
307
+ "-t",
308
+ action="store_true",
309
+ help="test if code is still up to date",
310
+ )
311
+ parsed_args = parser.parse_args()
312
+
313
+ source_root = Path.cwd()
314
+ # Double-check we found the right directory
315
+ assert (source_root / "LICENSE").exists()
316
+ core = source_root / "src/trio/_core"
317
+ to_wrap = [
318
+ File(core / "_run.py", "runner", imports=IMPORTS_RUN),
319
+ File(
320
+ core / "_instrumentation.py",
321
+ "runner.instruments",
322
+ imports=IMPORTS_INSTRUMENT,
323
+ ),
324
+ File(
325
+ core / "_io_windows.py",
326
+ "runner.io_manager",
327
+ platform="win32",
328
+ imports=IMPORTS_WINDOWS,
329
+ ),
330
+ File(
331
+ core / "_io_epoll.py",
332
+ "runner.io_manager",
333
+ platform="linux",
334
+ imports=IMPORTS_EPOLL,
335
+ ),
336
+ File(
337
+ core / "_io_kqueue.py",
338
+ "runner.io_manager",
339
+ platform="darwin",
340
+ imports=IMPORTS_KQUEUE,
341
+ ),
342
+ ]
343
+
344
+ process(to_wrap, do_test=parsed_args.test)
345
+
346
+
347
+ IMPORTS_RUN = """\
348
+ from collections.abc import Awaitable, Callable
349
+ from typing import Any, TYPE_CHECKING
350
+
351
+ import outcome
352
+ import contextvars
353
+
354
+ from ._run import _NO_SEND, RunStatistics, Task
355
+ from ._entry_queue import TrioToken
356
+ from .._abc import Clock
357
+
358
+ if TYPE_CHECKING:
359
+ from typing_extensions import Unpack
360
+ from ._run import PosArgT
361
+ """
362
+ IMPORTS_INSTRUMENT = """\
363
+ from ._instrumentation import Instrument
364
+ """
365
+
366
+ IMPORTS_EPOLL = """\
367
+ from typing import TYPE_CHECKING
368
+
369
+ if TYPE_CHECKING:
370
+ from .._file_io import _HasFileNo
371
+ """
372
+
373
+ IMPORTS_KQUEUE = """\
374
+ from typing import TYPE_CHECKING
375
+
376
+ if TYPE_CHECKING:
377
+ import select
378
+ from collections.abc import Callable
379
+ from contextlib import AbstractContextManager
380
+
381
+ from .. import _core
382
+ from .._file_io import _HasFileNo
383
+ from ._traps import Abort, RaiseCancelT
384
+ """
385
+
386
+ IMPORTS_WINDOWS = """\
387
+ from typing import TYPE_CHECKING
388
+
389
+ if TYPE_CHECKING:
390
+ from contextlib import AbstractContextManager
391
+
392
+ from typing_extensions import Buffer
393
+
394
+ from .._file_io import _HasFileNo
395
+ from ._unbounded_queue import UnboundedQueue
396
+ from ._windows_cffi import Handle, CData
397
+ """
398
+
399
+
400
+ if __name__ == "__main__":
401
+ main()