@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.
- package/bin/kgraph-launcher +15 -3
- package/lib/kgraph/scripts/build-bundle.sh +17 -4
- package/lib/site-packages/outcome/__init__.py +20 -0
- package/lib/site-packages/outcome/_impl.py +239 -0
- package/lib/site-packages/outcome/_util.py +33 -0
- package/lib/site-packages/outcome/_version.py +7 -0
- package/lib/site-packages/outcome/py.typed +0 -0
- package/lib/site-packages/outcome-1.3.0.post0.dist-info/INSTALLER +1 -0
- package/lib/site-packages/outcome-1.3.0.post0.dist-info/LICENSE +3 -0
- package/lib/site-packages/outcome-1.3.0.post0.dist-info/LICENSE.APACHE2 +202 -0
- package/lib/site-packages/outcome-1.3.0.post0.dist-info/LICENSE.MIT +20 -0
- package/lib/site-packages/outcome-1.3.0.post0.dist-info/METADATA +63 -0
- package/lib/site-packages/outcome-1.3.0.post0.dist-info/RECORD +13 -0
- package/lib/site-packages/outcome-1.3.0.post0.dist-info/WHEEL +6 -0
- package/lib/site-packages/outcome-1.3.0.post0.dist-info/top_level.txt +1 -0
- package/lib/site-packages/sniffio/__init__.py +17 -0
- package/lib/site-packages/sniffio/_impl.py +95 -0
- package/lib/site-packages/sniffio/_tests/__init__.py +0 -0
- package/lib/site-packages/sniffio/_tests/test_sniffio.py +84 -0
- package/lib/site-packages/sniffio/_version.py +3 -0
- package/lib/site-packages/sniffio/py.typed +0 -0
- package/lib/site-packages/sniffio-1.3.1.dist-info/INSTALLER +1 -0
- package/lib/site-packages/sniffio-1.3.1.dist-info/LICENSE +3 -0
- package/lib/site-packages/sniffio-1.3.1.dist-info/LICENSE.APACHE2 +202 -0
- package/lib/site-packages/sniffio-1.3.1.dist-info/LICENSE.MIT +20 -0
- package/lib/site-packages/sniffio-1.3.1.dist-info/METADATA +104 -0
- package/lib/site-packages/sniffio-1.3.1.dist-info/RECORD +14 -0
- package/lib/site-packages/sniffio-1.3.1.dist-info/WHEEL +5 -0
- package/lib/site-packages/sniffio-1.3.1.dist-info/top_level.txt +1 -0
- package/lib/site-packages/sortedcontainers/__init__.py +74 -0
- package/lib/site-packages/sortedcontainers/sorteddict.py +812 -0
- package/lib/site-packages/sortedcontainers/sortedlist.py +2646 -0
- package/lib/site-packages/sortedcontainers/sortedset.py +733 -0
- package/lib/site-packages/sortedcontainers-2.4.0.dist-info/INSTALLER +1 -0
- package/lib/site-packages/sortedcontainers-2.4.0.dist-info/LICENSE +13 -0
- package/lib/site-packages/sortedcontainers-2.4.0.dist-info/METADATA +264 -0
- package/lib/site-packages/sortedcontainers-2.4.0.dist-info/RECORD +10 -0
- package/lib/site-packages/sortedcontainers-2.4.0.dist-info/WHEEL +6 -0
- package/lib/site-packages/sortedcontainers-2.4.0.dist-info/top_level.txt +1 -0
- package/lib/site-packages/trio/__init__.py +133 -0
- package/lib/site-packages/trio/__main__.py +3 -0
- package/lib/site-packages/trio/_abc.py +714 -0
- package/lib/site-packages/trio/_channel.py +610 -0
- package/lib/site-packages/trio/_core/__init__.py +94 -0
- package/lib/site-packages/trio/_core/_asyncgens.py +243 -0
- package/lib/site-packages/trio/_core/_concat_tb.py +26 -0
- package/lib/site-packages/trio/_core/_entry_queue.py +223 -0
- package/lib/site-packages/trio/_core/_exceptions.py +169 -0
- package/lib/site-packages/trio/_core/_generated_instrumentation.py +50 -0
- package/lib/site-packages/trio/_core/_generated_io_epoll.py +98 -0
- package/lib/site-packages/trio/_core/_generated_io_kqueue.py +153 -0
- package/lib/site-packages/trio/_core/_generated_io_windows.py +204 -0
- package/lib/site-packages/trio/_core/_generated_run.py +269 -0
- package/lib/site-packages/trio/_core/_generated_windows_ffi.py +10 -0
- package/lib/site-packages/trio/_core/_instrumentation.py +117 -0
- package/lib/site-packages/trio/_core/_io_common.py +31 -0
- package/lib/site-packages/trio/_core/_io_epoll.py +385 -0
- package/lib/site-packages/trio/_core/_io_kqueue.py +292 -0
- package/lib/site-packages/trio/_core/_io_windows.py +1036 -0
- package/lib/site-packages/trio/_core/_ki.py +271 -0
- package/lib/site-packages/trio/_core/_local.py +104 -0
- package/lib/site-packages/trio/_core/_mock_clock.py +165 -0
- package/lib/site-packages/trio/_core/_parking_lot.py +317 -0
- package/lib/site-packages/trio/_core/_run.py +3148 -0
- package/lib/site-packages/trio/_core/_run_context.py +15 -0
- package/lib/site-packages/trio/_core/_tests/__init__.py +0 -0
- package/lib/site-packages/trio/_core/_tests/test_asyncgen.py +339 -0
- package/lib/site-packages/trio/_core/_tests/test_cancelled.py +222 -0
- package/lib/site-packages/trio/_core/_tests/test_exceptiongroup_gc.py +103 -0
- package/lib/site-packages/trio/_core/_tests/test_guest_mode.py +755 -0
- package/lib/site-packages/trio/_core/_tests/test_instrumentation.py +315 -0
- package/lib/site-packages/trio/_core/_tests/test_io.py +522 -0
- package/lib/site-packages/trio/_core/_tests/test_ki.py +703 -0
- package/lib/site-packages/trio/_core/_tests/test_local.py +118 -0
- package/lib/site-packages/trio/_core/_tests/test_mock_clock.py +193 -0
- package/lib/site-packages/trio/_core/_tests/test_parking_lot.py +389 -0
- package/lib/site-packages/trio/_core/_tests/test_run.py +3024 -0
- package/lib/site-packages/trio/_core/_tests/test_thread_cache.py +227 -0
- package/lib/site-packages/trio/_core/_tests/test_tutil.py +13 -0
- package/lib/site-packages/trio/_core/_tests/test_unbounded_queue.py +154 -0
- package/lib/site-packages/trio/_core/_tests/test_windows.py +305 -0
- package/lib/site-packages/trio/_core/_tests/tutil.py +117 -0
- package/lib/site-packages/trio/_core/_tests/type_tests/nursery_start.py +79 -0
- package/lib/site-packages/trio/_core/_tests/type_tests/run.py +51 -0
- package/lib/site-packages/trio/_core/_thread_cache.py +317 -0
- package/lib/site-packages/trio/_core/_traps.py +318 -0
- package/lib/site-packages/trio/_core/_unbounded_queue.py +163 -0
- package/lib/site-packages/trio/_core/_wakeup_socketpair.py +75 -0
- package/lib/site-packages/trio/_core/_windows_cffi.py +313 -0
- package/lib/site-packages/trio/_deprecate.py +171 -0
- package/lib/site-packages/trio/_dtls.py +1380 -0
- package/lib/site-packages/trio/_file_io.py +513 -0
- package/lib/site-packages/trio/_highlevel_generic.py +125 -0
- package/lib/site-packages/trio/_highlevel_open_tcp_listeners.py +251 -0
- package/lib/site-packages/trio/_highlevel_open_tcp_stream.py +397 -0
- package/lib/site-packages/trio/_highlevel_open_unix_stream.py +65 -0
- package/lib/site-packages/trio/_highlevel_serve_listeners.py +148 -0
- package/lib/site-packages/trio/_highlevel_socket.py +423 -0
- package/lib/site-packages/trio/_highlevel_ssl_helpers.py +180 -0
- package/lib/site-packages/trio/_path.py +289 -0
- package/lib/site-packages/trio/_repl.py +159 -0
- package/lib/site-packages/trio/_signals.py +185 -0
- package/lib/site-packages/trio/_socket.py +1326 -0
- package/lib/site-packages/trio/_ssl.py +964 -0
- package/lib/site-packages/trio/_subprocess.py +1178 -0
- package/lib/site-packages/trio/_subprocess_platform/__init__.py +123 -0
- package/lib/site-packages/trio/_subprocess_platform/kqueue.py +48 -0
- package/lib/site-packages/trio/_subprocess_platform/waitid.py +113 -0
- package/lib/site-packages/trio/_subprocess_platform/windows.py +11 -0
- package/lib/site-packages/trio/_sync.py +908 -0
- package/lib/site-packages/trio/_tests/__init__.py +0 -0
- package/lib/site-packages/trio/_tests/astrill-codesigning-cert.cer +0 -0
- package/lib/site-packages/trio/_tests/check_type_completeness.py +247 -0
- package/lib/site-packages/trio/_tests/module_with_deprecations.py +22 -0
- package/lib/site-packages/trio/_tests/pytest_plugin.py +54 -0
- package/lib/site-packages/trio/_tests/test_abc.py +72 -0
- package/lib/site-packages/trio/_tests/test_channel.py +750 -0
- package/lib/site-packages/trio/_tests/test_contextvars.py +56 -0
- package/lib/site-packages/trio/_tests/test_deprecate.py +277 -0
- package/lib/site-packages/trio/_tests/test_deprecate_strict_exception_groups_false.py +64 -0
- package/lib/site-packages/trio/_tests/test_dtls.py +950 -0
- package/lib/site-packages/trio/_tests/test_exports.py +626 -0
- package/lib/site-packages/trio/_tests/test_fakenet.py +317 -0
- package/lib/site-packages/trio/_tests/test_file_io.py +269 -0
- package/lib/site-packages/trio/_tests/test_highlevel_generic.py +98 -0
- package/lib/site-packages/trio/_tests/test_highlevel_open_tcp_listeners.py +419 -0
- package/lib/site-packages/trio/_tests/test_highlevel_open_tcp_stream.py +693 -0
- package/lib/site-packages/trio/_tests/test_highlevel_open_unix_stream.py +86 -0
- package/lib/site-packages/trio/_tests/test_highlevel_serve_listeners.py +186 -0
- package/lib/site-packages/trio/_tests/test_highlevel_socket.py +336 -0
- package/lib/site-packages/trio/_tests/test_highlevel_ssl_helpers.py +169 -0
- package/lib/site-packages/trio/_tests/test_path.py +279 -0
- package/lib/site-packages/trio/_tests/test_repl.py +428 -0
- package/lib/site-packages/trio/_tests/test_scheduler_determinism.py +47 -0
- package/lib/site-packages/trio/_tests/test_signals.py +186 -0
- package/lib/site-packages/trio/_tests/test_socket.py +1253 -0
- package/lib/site-packages/trio/_tests/test_ssl.py +1371 -0
- package/lib/site-packages/trio/_tests/test_subprocess.py +767 -0
- package/lib/site-packages/trio/_tests/test_sync.py +735 -0
- package/lib/site-packages/trio/_tests/test_testing.py +682 -0
- package/lib/site-packages/trio/_tests/test_testing_raisesgroup.py +1128 -0
- package/lib/site-packages/trio/_tests/test_threads.py +1173 -0
- package/lib/site-packages/trio/_tests/test_timeouts.py +281 -0
- package/lib/site-packages/trio/_tests/test_tracing.py +88 -0
- package/lib/site-packages/trio/_tests/test_trio.py +8 -0
- package/lib/site-packages/trio/_tests/test_unix_pipes.py +288 -0
- package/lib/site-packages/trio/_tests/test_util.py +349 -0
- package/lib/site-packages/trio/_tests/test_wait_for_object.py +225 -0
- package/lib/site-packages/trio/_tests/test_windows_pipes.py +112 -0
- package/lib/site-packages/trio/_tests/tools/__init__.py +0 -0
- package/lib/site-packages/trio/_tests/tools/test_gen_exports.py +179 -0
- package/lib/site-packages/trio/_tests/tools/test_mypy_annotate.py +140 -0
- package/lib/site-packages/trio/_tests/tools/test_sync_requirements.py +80 -0
- package/lib/site-packages/trio/_tests/type_tests/check_wraps.py +9 -0
- package/lib/site-packages/trio/_tests/type_tests/open_memory_channel.py +4 -0
- package/lib/site-packages/trio/_tests/type_tests/path.py +140 -0
- package/lib/site-packages/trio/_tests/type_tests/subprocesses.py +23 -0
- package/lib/site-packages/trio/_tests/type_tests/task_status.py +29 -0
- package/lib/site-packages/trio/_threads.py +610 -0
- package/lib/site-packages/trio/_timeouts.py +197 -0
- package/lib/site-packages/trio/_tools/__init__.py +0 -0
- package/lib/site-packages/trio/_tools/gen_exports.py +401 -0
- package/lib/site-packages/trio/_tools/mypy_annotate.py +126 -0
- package/lib/site-packages/trio/_tools/sync_requirements.py +98 -0
- package/lib/site-packages/trio/_tools/windows_ffi_build.py +220 -0
- package/lib/site-packages/trio/_unix_pipes.py +197 -0
- package/lib/site-packages/trio/_util.py +385 -0
- package/lib/site-packages/trio/_version.py +3 -0
- package/lib/site-packages/trio/_wait_for_object.py +67 -0
- package/lib/site-packages/trio/_windows_pipes.py +144 -0
- package/lib/site-packages/trio/abc.py +23 -0
- package/lib/site-packages/trio/from_thread.py +13 -0
- package/lib/site-packages/trio/lowlevel.py +95 -0
- package/lib/site-packages/trio/py.typed +0 -0
- package/lib/site-packages/trio/socket.py +602 -0
- package/lib/site-packages/trio/testing/__init__.py +58 -0
- package/lib/site-packages/trio/testing/_check_streams.py +570 -0
- package/lib/site-packages/trio/testing/_checkpoints.py +69 -0
- package/lib/site-packages/trio/testing/_fake_net.py +584 -0
- package/lib/site-packages/trio/testing/_memory_streams.py +633 -0
- package/lib/site-packages/trio/testing/_network.py +36 -0
- package/lib/site-packages/trio/testing/_raises_group.py +1015 -0
- package/lib/site-packages/trio/testing/_sequencer.py +87 -0
- package/lib/site-packages/trio/testing/_trio_test.py +50 -0
- package/lib/site-packages/trio/to_thread.py +4 -0
- package/lib/site-packages/trio-0.33.0.dist-info/INSTALLER +1 -0
- package/lib/site-packages/trio-0.33.0.dist-info/METADATA +186 -0
- package/lib/site-packages/trio-0.33.0.dist-info/RECORD +156 -0
- package/lib/site-packages/trio-0.33.0.dist-info/REQUESTED +0 -0
- package/lib/site-packages/trio-0.33.0.dist-info/WHEEL +5 -0
- package/lib/site-packages/trio-0.33.0.dist-info/entry_points.txt +2 -0
- package/lib/site-packages/trio-0.33.0.dist-info/licenses/LICENSE +3 -0
- package/lib/site-packages/trio-0.33.0.dist-info/licenses/LICENSE.APACHE2 +202 -0
- package/lib/site-packages/trio-0.33.0.dist-info/licenses/LICENSE.MIT +22 -0
- package/lib/site-packages/trio-0.33.0.dist-info/top_level.txt +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
"""Translates Mypy's output into GitHub's error/warning annotation syntax.
|
|
2
|
+
|
|
3
|
+
See: https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions
|
|
4
|
+
|
|
5
|
+
This first is run with Mypy's output piped in, to collect messages in
|
|
6
|
+
mypy_annotate.dat. After all platforms run, we run this again, which prints the
|
|
7
|
+
messages in GitHub's format but with cross-platform failures deduplicated.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
import argparse
|
|
13
|
+
import pickle
|
|
14
|
+
import re
|
|
15
|
+
import sys
|
|
16
|
+
|
|
17
|
+
import attrs
|
|
18
|
+
|
|
19
|
+
# Example: 'package/filename.py:42:1:46:3: error: Type error here [code]'
|
|
20
|
+
report_re = re.compile(
|
|
21
|
+
r"""
|
|
22
|
+
([^:]+): # Filename (anything but ":")
|
|
23
|
+
([0-9]+): # Line number (start)
|
|
24
|
+
(?:([0-9]+): # Optional column number
|
|
25
|
+
(?:([0-9]+):([0-9]+):)? # then also optionally, 2 more numbers for end columns
|
|
26
|
+
)?
|
|
27
|
+
\s*(error|warn|note): # Kind, prefixed with space
|
|
28
|
+
(.+) # Message
|
|
29
|
+
""",
|
|
30
|
+
re.VERBOSE,
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
mypy_to_github = {
|
|
34
|
+
"error": "error",
|
|
35
|
+
"warn": "warning",
|
|
36
|
+
"note": "notice",
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
@attrs.frozen(kw_only=True)
|
|
41
|
+
class Result:
|
|
42
|
+
"""Accumulated results, used as a dict key to deduplicate."""
|
|
43
|
+
|
|
44
|
+
filename: str
|
|
45
|
+
start_line: int
|
|
46
|
+
kind: str
|
|
47
|
+
message: str
|
|
48
|
+
start_col: int | None = None
|
|
49
|
+
end_line: int | None = None
|
|
50
|
+
end_col: int | None = None
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def process_line(line: str) -> Result | None:
|
|
54
|
+
if match := report_re.fullmatch(line.rstrip()):
|
|
55
|
+
filename, st_line, st_col, end_line, end_col, kind, message = match.groups()
|
|
56
|
+
return Result(
|
|
57
|
+
filename=filename,
|
|
58
|
+
start_line=int(st_line),
|
|
59
|
+
start_col=int(st_col) if st_col is not None else None,
|
|
60
|
+
end_line=int(end_line) if end_line is not None else None,
|
|
61
|
+
end_col=int(end_col) if end_col is not None else None,
|
|
62
|
+
kind=mypy_to_github[kind],
|
|
63
|
+
message=message,
|
|
64
|
+
)
|
|
65
|
+
else:
|
|
66
|
+
return None
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def export(results: dict[Result, list[str]]) -> None:
|
|
70
|
+
"""Display the collected results."""
|
|
71
|
+
for res, platforms in results.items():
|
|
72
|
+
print(f"::{res.kind} file={res.filename},line={res.start_line},", end="")
|
|
73
|
+
if res.start_col is not None:
|
|
74
|
+
print(f"col={res.start_col},", end="")
|
|
75
|
+
if res.end_col is not None and res.end_line is not None:
|
|
76
|
+
print(f"endLine={res.end_line},endColumn={res.end_col},", end="")
|
|
77
|
+
message = f"({res.start_line}:{res.start_col} - {res.end_line}:{res.end_col}):{res.message}"
|
|
78
|
+
else:
|
|
79
|
+
message = f"({res.start_line}:{res.start_col}):{res.message}"
|
|
80
|
+
else:
|
|
81
|
+
message = f"{res.start_line}:{res.message}"
|
|
82
|
+
print(f"title=Mypy-{'+'.join(platforms)}::{res.filename}:{message}")
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def main(argv: list[str]) -> None:
|
|
86
|
+
"""Look for error messages, and convert the format."""
|
|
87
|
+
parser = argparse.ArgumentParser(description=__doc__)
|
|
88
|
+
parser.add_argument(
|
|
89
|
+
"--dumpfile",
|
|
90
|
+
help="File to write pickled messages to.",
|
|
91
|
+
required=True,
|
|
92
|
+
)
|
|
93
|
+
parser.add_argument(
|
|
94
|
+
"--platform",
|
|
95
|
+
help="OS name, if set Mypy should be piped to stdin.",
|
|
96
|
+
default=None,
|
|
97
|
+
)
|
|
98
|
+
cmd_line = parser.parse_args(argv)
|
|
99
|
+
|
|
100
|
+
results: dict[Result, list[str]]
|
|
101
|
+
try:
|
|
102
|
+
with open(cmd_line.dumpfile, "rb") as f:
|
|
103
|
+
results = pickle.load(f)
|
|
104
|
+
except (FileNotFoundError, pickle.UnpicklingError):
|
|
105
|
+
# If we fail to load, assume it's an old result.
|
|
106
|
+
results = {}
|
|
107
|
+
|
|
108
|
+
if cmd_line.platform is None:
|
|
109
|
+
# Write out the results.
|
|
110
|
+
export(results)
|
|
111
|
+
else:
|
|
112
|
+
platform: str = cmd_line.platform
|
|
113
|
+
for line in sys.stdin:
|
|
114
|
+
parsed = process_line(line)
|
|
115
|
+
if parsed is not None:
|
|
116
|
+
try:
|
|
117
|
+
results[parsed].append(platform)
|
|
118
|
+
except KeyError:
|
|
119
|
+
results[parsed] = [platform]
|
|
120
|
+
sys.stdout.write(line)
|
|
121
|
+
with open(cmd_line.dumpfile, "wb") as f:
|
|
122
|
+
pickle.dump(results, f)
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
if __name__ == "__main__":
|
|
126
|
+
main(sys.argv[1:])
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
|
|
3
|
+
"""Sync Requirements - Automatically upgrade test requirements pinned
|
|
4
|
+
versions from pre-commit config file."""
|
|
5
|
+
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
|
|
8
|
+
import sys
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
from typing import TYPE_CHECKING
|
|
11
|
+
|
|
12
|
+
from yaml import load as load_yaml
|
|
13
|
+
|
|
14
|
+
if TYPE_CHECKING:
|
|
15
|
+
from collections.abc import Generator
|
|
16
|
+
|
|
17
|
+
from yaml import CLoader as _CLoader, Loader as _Loader
|
|
18
|
+
|
|
19
|
+
Loader: type[_CLoader | _Loader]
|
|
20
|
+
|
|
21
|
+
try:
|
|
22
|
+
from yaml import CLoader as Loader
|
|
23
|
+
except ImportError:
|
|
24
|
+
from yaml import Loader
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def yield_pre_commit_version_data(
|
|
28
|
+
pre_commit_text: str,
|
|
29
|
+
) -> Generator[tuple[str, str], None, None]:
|
|
30
|
+
"""Yield (name, rev) tuples from pre-commit config file."""
|
|
31
|
+
pre_commit_config = load_yaml(pre_commit_text, Loader)
|
|
32
|
+
for repo in pre_commit_config["repos"]:
|
|
33
|
+
if "repo" not in repo or "rev" not in repo:
|
|
34
|
+
continue
|
|
35
|
+
url = repo["repo"]
|
|
36
|
+
name = url.rsplit("/", 1)[-1]
|
|
37
|
+
rev = repo["rev"].removeprefix("v")
|
|
38
|
+
yield name, rev
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def update_requirements(
|
|
42
|
+
requirements: Path,
|
|
43
|
+
version_data: dict[str, str],
|
|
44
|
+
) -> bool:
|
|
45
|
+
"""Return if updated requirements file.
|
|
46
|
+
|
|
47
|
+
Update requirements file to match versions in version_data."""
|
|
48
|
+
changed = False
|
|
49
|
+
old_lines = requirements.read_text(encoding="utf-8").splitlines(True)
|
|
50
|
+
|
|
51
|
+
with requirements.open("w", encoding="utf-8") as file:
|
|
52
|
+
for line in old_lines:
|
|
53
|
+
# If comment or not version mark line, ignore.
|
|
54
|
+
if line.startswith("#") or "==" not in line:
|
|
55
|
+
file.write(line)
|
|
56
|
+
continue
|
|
57
|
+
name, rest = line.split("==", 1)
|
|
58
|
+
# Maintain extra markers if they exist
|
|
59
|
+
old_version = rest.strip()
|
|
60
|
+
extra = "\n"
|
|
61
|
+
if ";" in rest:
|
|
62
|
+
old_version, extra = rest.split(";", 1)
|
|
63
|
+
old_version = old_version.strip()
|
|
64
|
+
extra = " ;" + extra
|
|
65
|
+
version = version_data.get(name)
|
|
66
|
+
# If does not exist, skip
|
|
67
|
+
if version is None:
|
|
68
|
+
file.write(line)
|
|
69
|
+
continue
|
|
70
|
+
# Otherwise might have changed
|
|
71
|
+
new_line = f"{name}=={version}{extra}"
|
|
72
|
+
if new_line != line:
|
|
73
|
+
if not changed:
|
|
74
|
+
changed = True
|
|
75
|
+
print("Changed test requirements version to match pre-commit")
|
|
76
|
+
print(f"{name}=={old_version} -> {name}=={version}")
|
|
77
|
+
file.write(new_line)
|
|
78
|
+
return changed
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
if __name__ == "__main__":
|
|
82
|
+
source_root = Path.cwd().absolute()
|
|
83
|
+
|
|
84
|
+
# Double-check we found the right directory
|
|
85
|
+
assert (source_root / "LICENSE").exists()
|
|
86
|
+
pre_commit = source_root / ".pre-commit-config.yaml"
|
|
87
|
+
test_requirements = source_root / "test-requirements.txt"
|
|
88
|
+
|
|
89
|
+
pre_commit_text = pre_commit.read_text(encoding="utf-8")
|
|
90
|
+
|
|
91
|
+
# Get tool versions from pre-commit
|
|
92
|
+
# Get correct names
|
|
93
|
+
pre_commit_versions = {
|
|
94
|
+
name.removesuffix("-mirror").removesuffix("-pre-commit"): version
|
|
95
|
+
for name, version in yield_pre_commit_version_data(pre_commit_text)
|
|
96
|
+
}
|
|
97
|
+
changed = update_requirements(test_requirements, pre_commit_versions)
|
|
98
|
+
sys.exit(int(changed))
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
# builder for CFFI out-of-line mode, for reduced import time.
|
|
2
|
+
# run this to generate `trio._core._generated_windows_ffi`.
|
|
3
|
+
import re
|
|
4
|
+
|
|
5
|
+
import cffi
|
|
6
|
+
|
|
7
|
+
LIB = """
|
|
8
|
+
// https://msdn.microsoft.com/en-us/library/windows/desktop/aa383751(v=vs.85).aspx
|
|
9
|
+
typedef int BOOL;
|
|
10
|
+
typedef unsigned char BYTE;
|
|
11
|
+
typedef unsigned char UCHAR;
|
|
12
|
+
typedef BYTE BOOLEAN;
|
|
13
|
+
typedef void* PVOID;
|
|
14
|
+
typedef PVOID HANDLE;
|
|
15
|
+
typedef unsigned long DWORD;
|
|
16
|
+
typedef unsigned long ULONG;
|
|
17
|
+
typedef unsigned int NTSTATUS;
|
|
18
|
+
typedef unsigned long u_long;
|
|
19
|
+
typedef ULONG *PULONG;
|
|
20
|
+
typedef const void *LPCVOID;
|
|
21
|
+
typedef void *LPVOID;
|
|
22
|
+
typedef const wchar_t *LPCWSTR;
|
|
23
|
+
typedef DWORD* LPDWORD;
|
|
24
|
+
|
|
25
|
+
typedef uintptr_t ULONG_PTR;
|
|
26
|
+
typedef uintptr_t UINT_PTR;
|
|
27
|
+
|
|
28
|
+
typedef UINT_PTR SOCKET;
|
|
29
|
+
|
|
30
|
+
typedef struct _OVERLAPPED {
|
|
31
|
+
ULONG_PTR Internal;
|
|
32
|
+
ULONG_PTR InternalHigh;
|
|
33
|
+
union {
|
|
34
|
+
struct {
|
|
35
|
+
DWORD Offset;
|
|
36
|
+
DWORD OffsetHigh;
|
|
37
|
+
} DUMMYSTRUCTNAME;
|
|
38
|
+
PVOID Pointer;
|
|
39
|
+
} DUMMYUNIONNAME;
|
|
40
|
+
|
|
41
|
+
HANDLE hEvent;
|
|
42
|
+
} OVERLAPPED, *LPOVERLAPPED;
|
|
43
|
+
|
|
44
|
+
typedef OVERLAPPED WSAOVERLAPPED;
|
|
45
|
+
typedef LPOVERLAPPED LPWSAOVERLAPPED;
|
|
46
|
+
typedef PVOID LPSECURITY_ATTRIBUTES;
|
|
47
|
+
typedef PVOID LPCSTR;
|
|
48
|
+
|
|
49
|
+
typedef struct _OVERLAPPED_ENTRY {
|
|
50
|
+
ULONG_PTR lpCompletionKey;
|
|
51
|
+
LPOVERLAPPED lpOverlapped;
|
|
52
|
+
ULONG_PTR Internal;
|
|
53
|
+
DWORD dwNumberOfBytesTransferred;
|
|
54
|
+
} OVERLAPPED_ENTRY, *LPOVERLAPPED_ENTRY;
|
|
55
|
+
|
|
56
|
+
// kernel32.dll
|
|
57
|
+
HANDLE WINAPI CreateIoCompletionPort(
|
|
58
|
+
_In_ HANDLE FileHandle,
|
|
59
|
+
_In_opt_ HANDLE ExistingCompletionPort,
|
|
60
|
+
_In_ ULONG_PTR CompletionKey,
|
|
61
|
+
_In_ DWORD NumberOfConcurrentThreads
|
|
62
|
+
);
|
|
63
|
+
|
|
64
|
+
BOOL SetFileCompletionNotificationModes(
|
|
65
|
+
HANDLE FileHandle,
|
|
66
|
+
UCHAR Flags
|
|
67
|
+
);
|
|
68
|
+
|
|
69
|
+
HANDLE CreateFileW(
|
|
70
|
+
LPCWSTR lpFileName,
|
|
71
|
+
DWORD dwDesiredAccess,
|
|
72
|
+
DWORD dwShareMode,
|
|
73
|
+
LPSECURITY_ATTRIBUTES lpSecurityAttributes,
|
|
74
|
+
DWORD dwCreationDisposition,
|
|
75
|
+
DWORD dwFlagsAndAttributes,
|
|
76
|
+
HANDLE hTemplateFile
|
|
77
|
+
);
|
|
78
|
+
|
|
79
|
+
BOOL WINAPI CloseHandle(
|
|
80
|
+
_In_ HANDLE hObject
|
|
81
|
+
);
|
|
82
|
+
|
|
83
|
+
BOOL WINAPI PostQueuedCompletionStatus(
|
|
84
|
+
_In_ HANDLE CompletionPort,
|
|
85
|
+
_In_ DWORD dwNumberOfBytesTransferred,
|
|
86
|
+
_In_ ULONG_PTR dwCompletionKey,
|
|
87
|
+
_In_opt_ LPOVERLAPPED lpOverlapped
|
|
88
|
+
);
|
|
89
|
+
|
|
90
|
+
BOOL WINAPI GetQueuedCompletionStatusEx(
|
|
91
|
+
_In_ HANDLE CompletionPort,
|
|
92
|
+
_Out_ LPOVERLAPPED_ENTRY lpCompletionPortEntries,
|
|
93
|
+
_In_ ULONG ulCount,
|
|
94
|
+
_Out_ PULONG ulNumEntriesRemoved,
|
|
95
|
+
_In_ DWORD dwMilliseconds,
|
|
96
|
+
_In_ BOOL fAlertable
|
|
97
|
+
);
|
|
98
|
+
|
|
99
|
+
BOOL WINAPI CancelIoEx(
|
|
100
|
+
_In_ HANDLE hFile,
|
|
101
|
+
_In_opt_ LPOVERLAPPED lpOverlapped
|
|
102
|
+
);
|
|
103
|
+
|
|
104
|
+
BOOL WriteFile(
|
|
105
|
+
HANDLE hFile,
|
|
106
|
+
LPCVOID lpBuffer,
|
|
107
|
+
DWORD nNumberOfBytesToWrite,
|
|
108
|
+
LPDWORD lpNumberOfBytesWritten,
|
|
109
|
+
LPOVERLAPPED lpOverlapped
|
|
110
|
+
);
|
|
111
|
+
|
|
112
|
+
BOOL ReadFile(
|
|
113
|
+
HANDLE hFile,
|
|
114
|
+
LPVOID lpBuffer,
|
|
115
|
+
DWORD nNumberOfBytesToRead,
|
|
116
|
+
LPDWORD lpNumberOfBytesRead,
|
|
117
|
+
LPOVERLAPPED lpOverlapped
|
|
118
|
+
);
|
|
119
|
+
|
|
120
|
+
BOOL WINAPI SetConsoleCtrlHandler(
|
|
121
|
+
_In_opt_ void* HandlerRoutine,
|
|
122
|
+
_In_ BOOL Add
|
|
123
|
+
);
|
|
124
|
+
|
|
125
|
+
HANDLE CreateEventA(
|
|
126
|
+
LPSECURITY_ATTRIBUTES lpEventAttributes,
|
|
127
|
+
BOOL bManualReset,
|
|
128
|
+
BOOL bInitialState,
|
|
129
|
+
LPCSTR lpName
|
|
130
|
+
);
|
|
131
|
+
|
|
132
|
+
BOOL SetEvent(
|
|
133
|
+
HANDLE hEvent
|
|
134
|
+
);
|
|
135
|
+
|
|
136
|
+
BOOL ResetEvent(
|
|
137
|
+
HANDLE hEvent
|
|
138
|
+
);
|
|
139
|
+
|
|
140
|
+
DWORD WaitForSingleObject(
|
|
141
|
+
HANDLE hHandle,
|
|
142
|
+
DWORD dwMilliseconds
|
|
143
|
+
);
|
|
144
|
+
|
|
145
|
+
DWORD WaitForMultipleObjects(
|
|
146
|
+
DWORD nCount,
|
|
147
|
+
HANDLE *lpHandles,
|
|
148
|
+
BOOL bWaitAll,
|
|
149
|
+
DWORD dwMilliseconds
|
|
150
|
+
);
|
|
151
|
+
|
|
152
|
+
ULONG RtlNtStatusToDosError(
|
|
153
|
+
NTSTATUS Status
|
|
154
|
+
);
|
|
155
|
+
|
|
156
|
+
int WSAIoctl(
|
|
157
|
+
SOCKET s,
|
|
158
|
+
DWORD dwIoControlCode,
|
|
159
|
+
LPVOID lpvInBuffer,
|
|
160
|
+
DWORD cbInBuffer,
|
|
161
|
+
LPVOID lpvOutBuffer,
|
|
162
|
+
DWORD cbOutBuffer,
|
|
163
|
+
LPDWORD lpcbBytesReturned,
|
|
164
|
+
LPWSAOVERLAPPED lpOverlapped,
|
|
165
|
+
// actually LPWSAOVERLAPPED_COMPLETION_ROUTINE
|
|
166
|
+
void* lpCompletionRoutine
|
|
167
|
+
);
|
|
168
|
+
|
|
169
|
+
int WSAGetLastError();
|
|
170
|
+
|
|
171
|
+
BOOL DeviceIoControl(
|
|
172
|
+
HANDLE hDevice,
|
|
173
|
+
DWORD dwIoControlCode,
|
|
174
|
+
LPVOID lpInBuffer,
|
|
175
|
+
DWORD nInBufferSize,
|
|
176
|
+
LPVOID lpOutBuffer,
|
|
177
|
+
DWORD nOutBufferSize,
|
|
178
|
+
LPDWORD lpBytesReturned,
|
|
179
|
+
LPOVERLAPPED lpOverlapped
|
|
180
|
+
);
|
|
181
|
+
|
|
182
|
+
// From https://github.com/piscisaureus/wepoll/blob/master/src/afd.h
|
|
183
|
+
typedef struct _AFD_POLL_HANDLE_INFO {
|
|
184
|
+
HANDLE Handle;
|
|
185
|
+
ULONG Events;
|
|
186
|
+
NTSTATUS Status;
|
|
187
|
+
} AFD_POLL_HANDLE_INFO, *PAFD_POLL_HANDLE_INFO;
|
|
188
|
+
|
|
189
|
+
// This is really defined as a messy union to allow stuff like
|
|
190
|
+
// i.DUMMYSTRUCTNAME.LowPart, but we don't need those complications.
|
|
191
|
+
// Under all that it's just an int64.
|
|
192
|
+
typedef int64_t LARGE_INTEGER;
|
|
193
|
+
|
|
194
|
+
typedef struct _AFD_POLL_INFO {
|
|
195
|
+
LARGE_INTEGER Timeout;
|
|
196
|
+
ULONG NumberOfHandles;
|
|
197
|
+
ULONG Exclusive;
|
|
198
|
+
AFD_POLL_HANDLE_INFO Handles[1];
|
|
199
|
+
} AFD_POLL_INFO, *PAFD_POLL_INFO;
|
|
200
|
+
|
|
201
|
+
"""
|
|
202
|
+
|
|
203
|
+
# cribbed from pywincffi
|
|
204
|
+
# programmatically strips out those annotations MSDN likes, like _In_
|
|
205
|
+
LIB = re.sub(r"\b(_In_|_Inout_|_Out_|_Outptr_|_Reserved_)(opt_)?\b", " ", LIB)
|
|
206
|
+
|
|
207
|
+
# Other fixups:
|
|
208
|
+
# - get rid of FAR, cffi doesn't like it
|
|
209
|
+
LIB = re.sub(r"\bFAR\b", " ", LIB)
|
|
210
|
+
# - PASCAL is apparently an alias for __stdcall (on modern compilers - modern
|
|
211
|
+
# being _MSC_VER >= 800)
|
|
212
|
+
LIB = re.sub(r"\bPASCAL\b", "__stdcall", LIB)
|
|
213
|
+
|
|
214
|
+
ffibuilder = cffi.FFI()
|
|
215
|
+
# a bit hacky but, it works
|
|
216
|
+
ffibuilder.set_source("trio._core._generated_windows_ffi", None)
|
|
217
|
+
ffibuilder.cdef(LIB)
|
|
218
|
+
|
|
219
|
+
if __name__ == "__main__":
|
|
220
|
+
ffibuilder.compile("src")
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import errno
|
|
4
|
+
import os
|
|
5
|
+
import sys
|
|
6
|
+
from typing import TYPE_CHECKING, Final as FinalType
|
|
7
|
+
|
|
8
|
+
import trio
|
|
9
|
+
|
|
10
|
+
from ._abc import Stream
|
|
11
|
+
from ._util import ConflictDetector, final
|
|
12
|
+
|
|
13
|
+
assert not TYPE_CHECKING or sys.platform != "win32"
|
|
14
|
+
|
|
15
|
+
# XX TODO: is this a good number? who knows... it does match the default Linux
|
|
16
|
+
# pipe capacity though.
|
|
17
|
+
DEFAULT_RECEIVE_SIZE: FinalType = 65536
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class _FdHolder:
|
|
21
|
+
# This class holds onto a raw file descriptor, in non-blocking mode, and
|
|
22
|
+
# is responsible for managing its lifecycle. In particular, it's
|
|
23
|
+
# responsible for making sure it gets closed, and also for tracking
|
|
24
|
+
# whether it's been closed.
|
|
25
|
+
#
|
|
26
|
+
# The way we track closure is to set the .fd field to -1, discarding the
|
|
27
|
+
# original value. You might think that this is a strange idea, since it
|
|
28
|
+
# overloads the same field to do two different things. Wouldn't it be more
|
|
29
|
+
# natural to have a dedicated .closed field? But that would be more
|
|
30
|
+
# error-prone. Fds are represented by small integers, and once an fd is
|
|
31
|
+
# closed, its integer value may be reused immediately. If we accidentally
|
|
32
|
+
# used the old fd after being closed, we might end up doing something to
|
|
33
|
+
# another unrelated fd that happened to get assigned the same integer
|
|
34
|
+
# value. By throwing away the integer value immediately, it becomes
|
|
35
|
+
# impossible to make this mistake – we'll just get an EBADF.
|
|
36
|
+
#
|
|
37
|
+
# (This trick was copied from the stdlib socket module.)
|
|
38
|
+
fd: int
|
|
39
|
+
|
|
40
|
+
def __init__(self, fd: int) -> None:
|
|
41
|
+
# make sure self.fd is always initialized to *something*, because even
|
|
42
|
+
# if we error out here then __del__ will run and access it.
|
|
43
|
+
self.fd = -1
|
|
44
|
+
if not isinstance(fd, int):
|
|
45
|
+
raise TypeError("file descriptor must be an int")
|
|
46
|
+
self.fd = fd
|
|
47
|
+
# Store original state, and ensure non-blocking mode is enabled
|
|
48
|
+
self._original_is_blocking = os.get_blocking(fd)
|
|
49
|
+
os.set_blocking(fd, False)
|
|
50
|
+
|
|
51
|
+
@property
|
|
52
|
+
def closed(self) -> bool:
|
|
53
|
+
return self.fd == -1
|
|
54
|
+
|
|
55
|
+
def _raw_close(self) -> None:
|
|
56
|
+
# This doesn't assume it's in a Trio context, so it can be called from
|
|
57
|
+
# __del__. You should never call it from Trio context, because it
|
|
58
|
+
# skips calling notify_fd_close. But from __del__, skipping that is
|
|
59
|
+
# OK, because notify_fd_close just wakes up other tasks that are
|
|
60
|
+
# waiting on this fd, and those tasks hold a reference to this object.
|
|
61
|
+
# So if __del__ is being called, we know there aren't any tasks that
|
|
62
|
+
# need to be woken.
|
|
63
|
+
if self.closed:
|
|
64
|
+
return
|
|
65
|
+
fd = self.fd
|
|
66
|
+
self.fd = -1
|
|
67
|
+
os.set_blocking(fd, self._original_is_blocking)
|
|
68
|
+
os.close(fd)
|
|
69
|
+
|
|
70
|
+
def __del__(self) -> None:
|
|
71
|
+
self._raw_close()
|
|
72
|
+
|
|
73
|
+
def close(self) -> None:
|
|
74
|
+
if not self.closed:
|
|
75
|
+
trio.lowlevel.notify_closing(self.fd)
|
|
76
|
+
self._raw_close()
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
@final
|
|
80
|
+
class FdStream(Stream):
|
|
81
|
+
"""Represents a stream given the file descriptor to a pipe, TTY, etc.
|
|
82
|
+
|
|
83
|
+
*fd* must refer to a file that is open for reading and/or writing and
|
|
84
|
+
supports non-blocking I/O (pipes and TTYs will work, on-disk files probably
|
|
85
|
+
not). The returned stream takes ownership of the fd, so closing the stream
|
|
86
|
+
will close the fd too. As with `os.fdopen`, you should not directly use
|
|
87
|
+
an fd after you have wrapped it in a stream using this function.
|
|
88
|
+
|
|
89
|
+
To be used as a Trio stream, an open file must be placed in non-blocking
|
|
90
|
+
mode. Unfortunately, this impacts all I/O that goes through the
|
|
91
|
+
underlying open file, including I/O that uses a different
|
|
92
|
+
file descriptor than the one that was passed to Trio. If other threads
|
|
93
|
+
or processes are using file descriptors that are related through `os.dup`
|
|
94
|
+
or inheritance across `os.fork` to the one that Trio is using, they are
|
|
95
|
+
unlikely to be prepared to have non-blocking I/O semantics suddenly
|
|
96
|
+
thrust upon them. For example, you can use
|
|
97
|
+
``FdStream(os.dup(sys.stdin.fileno()))`` to obtain a stream for reading
|
|
98
|
+
from standard input, but it is only safe to do so with heavy caveats: your
|
|
99
|
+
stdin must not be shared by any other processes, and you must not make any
|
|
100
|
+
calls to synchronous methods of `sys.stdin` until the stream returned by
|
|
101
|
+
`FdStream` is closed. See `issue #174
|
|
102
|
+
<https://github.com/python-trio/trio/issues/174>`__ for a discussion of the
|
|
103
|
+
challenges involved in relaxing this restriction.
|
|
104
|
+
|
|
105
|
+
.. warning:: one specific consequence of non-blocking mode
|
|
106
|
+
applying to the entire open file description is that when
|
|
107
|
+
your program is run with multiple standard streams connected to
|
|
108
|
+
a TTY (as in a terminal emulator), all of the streams become
|
|
109
|
+
non-blocking when you construct an `FdStream` for any of them.
|
|
110
|
+
For example, if you construct an `FdStream` for standard input,
|
|
111
|
+
you might observe Python loggers begin to fail with
|
|
112
|
+
`BlockingIOError`.
|
|
113
|
+
|
|
114
|
+
Args:
|
|
115
|
+
fd (int): The fd to be wrapped.
|
|
116
|
+
|
|
117
|
+
Returns:
|
|
118
|
+
A new `FdStream` object.
|
|
119
|
+
"""
|
|
120
|
+
|
|
121
|
+
def __init__(self, fd: int) -> None:
|
|
122
|
+
self._fd_holder = _FdHolder(fd)
|
|
123
|
+
self._send_conflict_detector = ConflictDetector(
|
|
124
|
+
"another task is using this stream for send",
|
|
125
|
+
)
|
|
126
|
+
self._receive_conflict_detector = ConflictDetector(
|
|
127
|
+
"another task is using this stream for receive",
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
async def send_all(self, data: bytes) -> None:
|
|
131
|
+
with self._send_conflict_detector:
|
|
132
|
+
# have to check up front, because send_all(b"") on a closed pipe
|
|
133
|
+
# should raise
|
|
134
|
+
if self._fd_holder.closed:
|
|
135
|
+
raise trio.ClosedResourceError("file was already closed")
|
|
136
|
+
await trio.lowlevel.checkpoint()
|
|
137
|
+
length = len(data)
|
|
138
|
+
# adapted from the SocketStream code
|
|
139
|
+
with memoryview(data) as view:
|
|
140
|
+
sent = 0
|
|
141
|
+
while sent < length:
|
|
142
|
+
with view[sent:] as remaining:
|
|
143
|
+
try:
|
|
144
|
+
sent += os.write(self._fd_holder.fd, remaining)
|
|
145
|
+
except BlockingIOError:
|
|
146
|
+
await trio.lowlevel.wait_writable(self._fd_holder.fd)
|
|
147
|
+
except OSError as e:
|
|
148
|
+
if e.errno == errno.EBADF:
|
|
149
|
+
raise trio.ClosedResourceError(
|
|
150
|
+
"file was already closed",
|
|
151
|
+
) from None
|
|
152
|
+
else:
|
|
153
|
+
raise trio.BrokenResourceError from e
|
|
154
|
+
|
|
155
|
+
async def wait_send_all_might_not_block(self) -> None:
|
|
156
|
+
with self._send_conflict_detector:
|
|
157
|
+
if self._fd_holder.closed:
|
|
158
|
+
raise trio.ClosedResourceError("file was already closed")
|
|
159
|
+
await trio.lowlevel.wait_writable(self._fd_holder.fd)
|
|
160
|
+
|
|
161
|
+
async def receive_some(self, max_bytes: int | None = None) -> bytes:
|
|
162
|
+
with self._receive_conflict_detector:
|
|
163
|
+
if max_bytes is None:
|
|
164
|
+
max_bytes = DEFAULT_RECEIVE_SIZE
|
|
165
|
+
else:
|
|
166
|
+
if not isinstance(max_bytes, int):
|
|
167
|
+
raise TypeError("max_bytes must be integer >= 1")
|
|
168
|
+
if max_bytes < 1:
|
|
169
|
+
raise ValueError("max_bytes must be integer >= 1")
|
|
170
|
+
|
|
171
|
+
await trio.lowlevel.checkpoint()
|
|
172
|
+
while True:
|
|
173
|
+
try:
|
|
174
|
+
data = os.read(self._fd_holder.fd, max_bytes)
|
|
175
|
+
except BlockingIOError:
|
|
176
|
+
await trio.lowlevel.wait_readable(self._fd_holder.fd)
|
|
177
|
+
except OSError as exc:
|
|
178
|
+
if exc.errno == errno.EBADF:
|
|
179
|
+
raise trio.ClosedResourceError(
|
|
180
|
+
"file was already closed",
|
|
181
|
+
) from None
|
|
182
|
+
else:
|
|
183
|
+
raise trio.BrokenResourceError from exc
|
|
184
|
+
else:
|
|
185
|
+
break
|
|
186
|
+
|
|
187
|
+
return data
|
|
188
|
+
|
|
189
|
+
def close(self) -> None:
|
|
190
|
+
self._fd_holder.close()
|
|
191
|
+
|
|
192
|
+
async def aclose(self) -> None:
|
|
193
|
+
self.close()
|
|
194
|
+
await trio.lowlevel.checkpoint()
|
|
195
|
+
|
|
196
|
+
def fileno(self) -> int:
|
|
197
|
+
return self._fd_holder.fd
|