fancy-subprocess 2.2__tar.gz → 2.4__tar.gz
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.
- {fancy_subprocess-2.2 → fancy_subprocess-2.4}/.gitignore +1 -0
- fancy_subprocess-2.4/Justfile +27 -0
- {fancy_subprocess-2.2 → fancy_subprocess-2.4}/PKG-INFO +16 -4
- {fancy_subprocess-2.2 → fancy_subprocess-2.4}/README.md +13 -2
- {fancy_subprocess-2.2 → fancy_subprocess-2.4}/fancy_subprocess/__init__.py +1 -0
- {fancy_subprocess-2.2 → fancy_subprocess-2.4}/fancy_subprocess/_compat.py +5 -2
- fancy_subprocess-2.4/fancy_subprocess/_exit_code.py +53 -0
- {fancy_subprocess-2.2 → fancy_subprocess-2.4}/fancy_subprocess/_print.py +7 -2
- {fancy_subprocess-2.2 → fancy_subprocess-2.4}/fancy_subprocess/_reconfigure.py +5 -1
- {fancy_subprocess-2.2 → fancy_subprocess-2.4}/fancy_subprocess/_run_core.py +33 -12
- {fancy_subprocess-2.2 → fancy_subprocess-2.4}/fancy_subprocess/_run_param.py +14 -5
- {fancy_subprocess-2.2 → fancy_subprocess-2.4}/fancy_subprocess/_run_wrappers.py +11 -4
- fancy_subprocess-2.4/fancy_subprocess/_utils.py +23 -0
- {fancy_subprocess-2.2 → fancy_subprocess-2.4}/pyproject.toml +40 -2
- fancy_subprocess-2.4/uv.lock +261 -0
- fancy_subprocess-2.2/fancy_subprocess/_utils.py +0 -52
- fancy_subprocess-2.2/grab_output.py +0 -26
- fancy_subprocess-2.2/uv.lock +0 -96
- {fancy_subprocess-2.2 → fancy_subprocess-2.4}/.editorconfig +0 -0
- {fancy_subprocess-2.2 → fancy_subprocess-2.4}/LICENSE +0 -0
- {fancy_subprocess-2.2 → fancy_subprocess-2.4}/fancy_subprocess/py.typed +0 -0
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
default:
|
|
2
|
+
just --list --justfile "{{justfile()}}"
|
|
3
|
+
|
|
4
|
+
[private]
|
|
5
|
+
verify_with_impl python_minor_version $UV_PROJECT_ENVIRONMENT:
|
|
6
|
+
uv sync --python 3.{{python_minor_version}}
|
|
7
|
+
|
|
8
|
+
uv run -m mypy .
|
|
9
|
+
uv run ty check .
|
|
10
|
+
uv run ruff check --target-version py3{{python_minor_version}}
|
|
11
|
+
uv run ruff format --check --target-version py3{{python_minor_version}}
|
|
12
|
+
|
|
13
|
+
verify_with python_minor_version="14": (verify_with_impl python_minor_version ".just_venv_3_"+python_minor_version)
|
|
14
|
+
|
|
15
|
+
verify: (verify_with "10") (verify_with "11") (verify_with "12") (verify_with "13") (verify_with "14")
|
|
16
|
+
|
|
17
|
+
format:
|
|
18
|
+
uv run ruff check --select I --fix
|
|
19
|
+
uv run ruff format
|
|
20
|
+
|
|
21
|
+
build_no_verify:
|
|
22
|
+
uv build
|
|
23
|
+
|
|
24
|
+
build: verify build_no_verify
|
|
25
|
+
|
|
26
|
+
publish: build
|
|
27
|
+
uv publish
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: fancy-subprocess
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.4
|
|
4
4
|
Summary: subprocess.run() with formatted output, detailed error messages and retry capabilities
|
|
5
5
|
Project-URL: Homepage, https://github.com/petamas/python-fancy-subprocess
|
|
6
6
|
Project-URL: Bug Tracker, https://github.com/petamas/python-fancy-subprocess/issues
|
|
@@ -17,8 +17,9 @@ Classifier: Programming Language :: Python :: 3.10
|
|
|
17
17
|
Classifier: Programming Language :: Python :: 3.11
|
|
18
18
|
Classifier: Programming Language :: Python :: 3.12
|
|
19
19
|
Classifier: Programming Language :: Python :: 3.13
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
20
21
|
Requires-Python: >=3.10
|
|
21
|
-
Requires-Dist: ntstatus<2
|
|
22
|
+
Requires-Dist: ntstatus<3,>=2.0
|
|
22
23
|
Requires-Dist: oslex<2,>=0.1.3
|
|
23
24
|
Requires-Dist: pathext<2,>=1.5
|
|
24
25
|
Requires-Dist: typeguard<5,>=4.4.2
|
|
@@ -40,7 +41,7 @@ Key differences compared to `subprocess.run()`:
|
|
|
40
41
|
- The output of the command is always captured, but it is also immediately printed using `print_output`.
|
|
41
42
|
- The exit code of the command is checked, and an exception is raised on failure, like `subprocess.run(check=True)`, but the list of exit codes treated as success is customizable, and the raised exception is `RunError` instead of `CalledProcessError`.
|
|
42
43
|
- `OSError` is never raised, it gets converted to `RunError`.
|
|
43
|
-
- `RunResult` is returned instead of `CompletedProcess` on success
|
|
44
|
+
- `RunResult` is returned instead of `CompletedProcess` on success.
|
|
44
45
|
|
|
45
46
|
Arguments (all of them except `cmd` are optional):
|
|
46
47
|
- `cmd: Sequence[str | Path]` - Command to run. See `subprocess.run()`'s documentation for the interpretation of `cmd[0]`. It is recommended to use `fancy_subprocess.which()` to produce `cmd[0]`.
|
|
@@ -224,7 +225,7 @@ except fancy_subprocess.RunError as e:
|
|
|
224
225
|
print(e)
|
|
225
226
|
```
|
|
226
227
|
|
|
227
|
-
Running the script on Windows will produce the following output
|
|
228
|
+
Running the script on Windows will produce the following output (-1072103376 is the signed integer interpretation of 0xC0190030, i.e. `STATUS_LOG_CORRUPTION_DETECTED`):
|
|
228
229
|
|
|
229
230
|
```
|
|
230
231
|
Demonstrating failure...
|
|
@@ -282,6 +283,17 @@ Exception FileNotFoundError with message "[Errno 2] No such file or directory: '
|
|
|
282
283
|
|
|
283
284
|
Calls `sys.stdout.reconfigure()` and `sys.stderr.reconfigure()` with the provided parameters. Raises `TypeError` if either `sys.stdout` or `sys.stderr` is not an instance of `io.TextIOWrapper`.
|
|
284
285
|
|
|
286
|
+
### `fancy_subprocess.stringify_exit_code()`
|
|
287
|
+
|
|
288
|
+
Takes an exit code, and tries to format it in a way to help users understand what went wrong. If it succeeds, returns the explanation as a string. If not, returns `None`.
|
|
289
|
+
|
|
290
|
+
Some examples:
|
|
291
|
+
- On POSIX platforms, decodes signals to their string representation.
|
|
292
|
+
- On Windows, if the code matches an NTSTATUS error, it returns the name of the NTSTATUS.
|
|
293
|
+
- On Windows, if it is a 32-bit value, returns it as a hex number (because that's usually how you can find them on Google).
|
|
294
|
+
|
|
295
|
+
Used as part of the error message in `RunError`.
|
|
296
|
+
|
|
285
297
|
## Licensing
|
|
286
298
|
|
|
287
299
|
This library is licensed under the MIT license.
|
|
@@ -13,7 +13,7 @@ Key differences compared to `subprocess.run()`:
|
|
|
13
13
|
- The output of the command is always captured, but it is also immediately printed using `print_output`.
|
|
14
14
|
- The exit code of the command is checked, and an exception is raised on failure, like `subprocess.run(check=True)`, but the list of exit codes treated as success is customizable, and the raised exception is `RunError` instead of `CalledProcessError`.
|
|
15
15
|
- `OSError` is never raised, it gets converted to `RunError`.
|
|
16
|
-
- `RunResult` is returned instead of `CompletedProcess` on success
|
|
16
|
+
- `RunResult` is returned instead of `CompletedProcess` on success.
|
|
17
17
|
|
|
18
18
|
Arguments (all of them except `cmd` are optional):
|
|
19
19
|
- `cmd: Sequence[str | Path]` - Command to run. See `subprocess.run()`'s documentation for the interpretation of `cmd[0]`. It is recommended to use `fancy_subprocess.which()` to produce `cmd[0]`.
|
|
@@ -197,7 +197,7 @@ except fancy_subprocess.RunError as e:
|
|
|
197
197
|
print(e)
|
|
198
198
|
```
|
|
199
199
|
|
|
200
|
-
Running the script on Windows will produce the following output
|
|
200
|
+
Running the script on Windows will produce the following output (-1072103376 is the signed integer interpretation of 0xC0190030, i.e. `STATUS_LOG_CORRUPTION_DETECTED`):
|
|
201
201
|
|
|
202
202
|
```
|
|
203
203
|
Demonstrating failure...
|
|
@@ -255,6 +255,17 @@ Exception FileNotFoundError with message "[Errno 2] No such file or directory: '
|
|
|
255
255
|
|
|
256
256
|
Calls `sys.stdout.reconfigure()` and `sys.stderr.reconfigure()` with the provided parameters. Raises `TypeError` if either `sys.stdout` or `sys.stderr` is not an instance of `io.TextIOWrapper`.
|
|
257
257
|
|
|
258
|
+
### `fancy_subprocess.stringify_exit_code()`
|
|
259
|
+
|
|
260
|
+
Takes an exit code, and tries to format it in a way to help users understand what went wrong. If it succeeds, returns the explanation as a string. If not, returns `None`.
|
|
261
|
+
|
|
262
|
+
Some examples:
|
|
263
|
+
- On POSIX platforms, decodes signals to their string representation.
|
|
264
|
+
- On Windows, if the code matches an NTSTATUS error, it returns the name of the NTSTATUS.
|
|
265
|
+
- On Windows, if it is a 32-bit value, returns it as a hex number (because that's usually how you can find them on Google).
|
|
266
|
+
|
|
267
|
+
Used as part of the error message in `RunError`.
|
|
268
|
+
|
|
258
269
|
## Licensing
|
|
259
270
|
|
|
260
271
|
This library is licensed under the MIT license.
|
|
@@ -6,13 +6,16 @@ __all__ = [
|
|
|
6
6
|
'which',
|
|
7
7
|
]
|
|
8
8
|
|
|
9
|
-
from pathext import checked_which
|
|
9
|
+
from pathext import checked_which
|
|
10
|
+
from pathext import which
|
|
10
11
|
|
|
11
|
-
from fancy_subprocess._run_core import RunError
|
|
12
|
+
from fancy_subprocess._run_core import RunError
|
|
13
|
+
from fancy_subprocess._run_core import RunResult
|
|
12
14
|
|
|
13
15
|
RunProcessError = RunError
|
|
14
16
|
RunProcessResult = RunResult
|
|
15
17
|
|
|
18
|
+
|
|
16
19
|
def SILENCE(msg: str) -> None:
|
|
17
20
|
"""
|
|
18
21
|
Helper function that takes a string, and does nothing with it. Meant to be passed as the print_message or print_output argument of run() and related functions to silence the corresponding output stream.
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
__all__ = [
|
|
2
|
+
'stringify_exit_code',
|
|
3
|
+
]
|
|
4
|
+
|
|
5
|
+
import sys
|
|
6
|
+
from typing import Optional
|
|
7
|
+
|
|
8
|
+
if sys.platform == 'win32':
|
|
9
|
+
from ntstatus import NtStatus
|
|
10
|
+
from ntstatus import NtStatusSeverity
|
|
11
|
+
from ntstatus import ThirtyTwoBits
|
|
12
|
+
else:
|
|
13
|
+
import signal
|
|
14
|
+
|
|
15
|
+
def _signal_name(signal_value: int) -> Optional[str]:
|
|
16
|
+
try:
|
|
17
|
+
return signal.Signals(signal_value).name
|
|
18
|
+
except ValueError:
|
|
19
|
+
return None
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def stringify_exit_code(exit_code: int) -> Optional[str]:
|
|
23
|
+
if sys.platform == 'win32':
|
|
24
|
+
# Windows
|
|
25
|
+
if exit_code == 3:
|
|
26
|
+
# abort() results in exit code 3: https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/abort
|
|
27
|
+
# While exit code 3 does not necessarily mean aborted (because applications may use it as a generic error code),
|
|
28
|
+
# it's common enough to be worth handling. "?" included to signal the uncertainty.
|
|
29
|
+
return 'aborted?'
|
|
30
|
+
|
|
31
|
+
if not ThirtyTwoBits.check(exit_code):
|
|
32
|
+
return None
|
|
33
|
+
|
|
34
|
+
try:
|
|
35
|
+
status = NtStatus.decode(exit_code)
|
|
36
|
+
if NtStatus.severity(status) != NtStatusSeverity.STATUS_SEVERITY_SUCCESS:
|
|
37
|
+
return status.name
|
|
38
|
+
except ValueError:
|
|
39
|
+
pass
|
|
40
|
+
|
|
41
|
+
return f'0x{ThirtyTwoBits(exit_code).unsigned_value:08X}'
|
|
42
|
+
else:
|
|
43
|
+
# POSIX
|
|
44
|
+
if exit_code < 0:
|
|
45
|
+
return _signal_name(-exit_code) or 'unknown signal'
|
|
46
|
+
elif exit_code == 126:
|
|
47
|
+
return 'COULD_NOT_EXECUTE'
|
|
48
|
+
elif exit_code == 127:
|
|
49
|
+
return 'COMMAND_NOT_FOUND'
|
|
50
|
+
elif exit_code in range(129, 160):
|
|
51
|
+
return _signal_name(exit_code - 128) or 'unknown signal'
|
|
52
|
+
|
|
53
|
+
return None
|
|
@@ -16,24 +16,29 @@ PrintFunction = Callable[[str], None]
|
|
|
16
16
|
|
|
17
17
|
Indent = int | str
|
|
18
18
|
|
|
19
|
+
|
|
19
20
|
def silenced_print(line: str) -> None:
|
|
20
21
|
pass
|
|
21
22
|
|
|
23
|
+
|
|
22
24
|
def indented_print(line: str, indent: Optional[Indent] = None) -> None:
|
|
23
25
|
if indent is None:
|
|
24
|
-
real_indent = 4*' '
|
|
26
|
+
real_indent = 4 * ' '
|
|
25
27
|
elif isinstance(indent, int):
|
|
26
|
-
real_indent = indent*' '
|
|
28
|
+
real_indent = indent * ' '
|
|
27
29
|
else:
|
|
28
30
|
real_indent = indent
|
|
29
31
|
|
|
30
32
|
print(f'{real_indent}{line}', flush=True)
|
|
31
33
|
|
|
34
|
+
|
|
32
35
|
def indented_print_factory(indent: Optional[Indent] = None) -> PrintFunction:
|
|
33
36
|
return lambda line: indented_print(line, indent)
|
|
34
37
|
|
|
38
|
+
|
|
35
39
|
def default_print(line: str) -> None:
|
|
36
40
|
indented_print(line, indent='')
|
|
37
41
|
|
|
42
|
+
|
|
38
43
|
def error_print(line: str) -> None:
|
|
39
44
|
print(line, file=sys.stderr, flush=True)
|
|
@@ -4,10 +4,12 @@ __all__ = [
|
|
|
4
4
|
|
|
5
5
|
import io
|
|
6
6
|
import sys
|
|
7
|
-
from typing import Optional
|
|
7
|
+
from typing import Optional
|
|
8
|
+
from typing import TypedDict
|
|
8
9
|
|
|
9
10
|
from typing_extensions import Unpack
|
|
10
11
|
|
|
12
|
+
|
|
11
13
|
class ReconfigureParams(TypedDict, total=False):
|
|
12
14
|
encoding: Optional[str]
|
|
13
15
|
errors: Optional[str]
|
|
@@ -15,6 +17,7 @@ class ReconfigureParams(TypedDict, total=False):
|
|
|
15
17
|
line_buffering: Optional[bool]
|
|
16
18
|
write_through: Optional[bool]
|
|
17
19
|
|
|
20
|
+
|
|
18
21
|
def _reconfigure_standard_stream(stream: object, name: str, **kwargs: Unpack[ReconfigureParams]) -> None:
|
|
19
22
|
if stream is None:
|
|
20
23
|
raise TypeError(f'{name} is None')
|
|
@@ -24,6 +27,7 @@ def _reconfigure_standard_stream(stream: object, name: str, **kwargs: Unpack[Rec
|
|
|
24
27
|
|
|
25
28
|
stream.reconfigure(**kwargs)
|
|
26
29
|
|
|
30
|
+
|
|
27
31
|
def reconfigure_standard_output_streams(**kwargs: Unpack[ReconfigureParams]) -> None:
|
|
28
32
|
"""
|
|
29
33
|
Calls `sys.stdout.reconfigure()` and `sys.stderr.reconfigure()` with the provided parameters. Raises `TypeError` if either `sys.stdout` or `sys.stderr` is not an instance of `io.TextIOWrapper`.
|
|
@@ -15,9 +15,17 @@ from typing import Optional
|
|
|
15
15
|
|
|
16
16
|
from typing_extensions import Unpack
|
|
17
17
|
|
|
18
|
-
from fancy_subprocess.
|
|
19
|
-
from fancy_subprocess.
|
|
20
|
-
from fancy_subprocess.
|
|
18
|
+
from fancy_subprocess._exit_code import stringify_exit_code
|
|
19
|
+
from fancy_subprocess._print import PrintFunction
|
|
20
|
+
from fancy_subprocess._print import default_print
|
|
21
|
+
from fancy_subprocess._print import silenced_print
|
|
22
|
+
from fancy_subprocess._run_param import AnyExitCode
|
|
23
|
+
from fancy_subprocess._run_param import RunParams
|
|
24
|
+
from fancy_subprocess._run_param import Success
|
|
25
|
+
from fancy_subprocess._run_param import check_run_params
|
|
26
|
+
from fancy_subprocess._utils import oslex_join
|
|
27
|
+
from fancy_subprocess._utils import value_or
|
|
28
|
+
|
|
21
29
|
|
|
22
30
|
@dataclass(kw_only=True, frozen=True)
|
|
23
31
|
class RunResult:
|
|
@@ -32,6 +40,7 @@ class RunResult:
|
|
|
32
40
|
exit_code: int = 0
|
|
33
41
|
output: str = ''
|
|
34
42
|
|
|
43
|
+
|
|
35
44
|
@dataclass(kw_only=True, frozen=True)
|
|
36
45
|
class RunError(Exception):
|
|
37
46
|
"""
|
|
@@ -96,6 +105,7 @@ class RunError(Exception):
|
|
|
96
105
|
def __str__(self) -> str:
|
|
97
106
|
return self.message
|
|
98
107
|
|
|
108
|
+
|
|
99
109
|
def run(
|
|
100
110
|
cmd: Sequence[str | Path],
|
|
101
111
|
*,
|
|
@@ -113,7 +123,7 @@ def run(
|
|
|
113
123
|
- The output of the command is always captured, but it is also immediately printed using `print_output`.
|
|
114
124
|
- The exit code of the command is checked, and an exception is raised on failure, like `subprocess.run(check=True)`, but the list of exit codes treated as success is customizable, and the raised exception is `RunError` instead of `CalledProcessError`.
|
|
115
125
|
- `OSError` is never raised, it gets converted to `RunError`.
|
|
116
|
-
- `RunResult` is returned instead of `CompletedProcess` on success
|
|
126
|
+
- `RunResult` is returned instead of `CompletedProcess` on success.
|
|
117
127
|
|
|
118
128
|
Arguments (all of them except `cmd` are optional):
|
|
119
129
|
- `cmd: Sequence[str | Path]` - Command to run. See `subprocess.run()`'s documentation for the interpretation of `cmd[0]`. It is recommended to use `fancy_subprocess.which()` to produce `cmd[0]`.
|
|
@@ -148,7 +158,7 @@ def run(
|
|
|
148
158
|
success: Success = value_or(kwargs.get('success'), [0])
|
|
149
159
|
flush_before_subprocess = value_or(kwargs.get('flush_before_subprocess'), True)
|
|
150
160
|
trim_output_lines = value_or(kwargs.get('trim_output_lines'), True)
|
|
151
|
-
max_output_size = value_or(kwargs.get('max_output_size'), 10*1000*1000)
|
|
161
|
+
max_output_size = value_or(kwargs.get('max_output_size'), 10 * 1000 * 1000)
|
|
152
162
|
retry = value_or(kwargs.get('retry'), 0)
|
|
153
163
|
retry_initial_sleep_seconds = value_or(kwargs.get('retry_initial_sleep_seconds'), 10)
|
|
154
164
|
retry_backoff = value_or(kwargs.get('retry_backoff'), 2)
|
|
@@ -169,8 +179,8 @@ def run(
|
|
|
169
179
|
print_output = value_or(print_output, default_print)
|
|
170
180
|
|
|
171
181
|
env = dict(os.environ)
|
|
172
|
-
if sys.platform=='win32':
|
|
173
|
-
env.update((key.upper(), value) for key,value in env_overrides.items())
|
|
182
|
+
if sys.platform == 'win32':
|
|
183
|
+
env.update((key.upper(), value) for key, value in env_overrides.items())
|
|
174
184
|
else:
|
|
175
185
|
env.update(env_overrides)
|
|
176
186
|
|
|
@@ -183,8 +193,19 @@ def run(
|
|
|
183
193
|
|
|
184
194
|
output = ''
|
|
185
195
|
try:
|
|
186
|
-
with subprocess.Popen(
|
|
187
|
-
|
|
196
|
+
with subprocess.Popen(
|
|
197
|
+
cmd,
|
|
198
|
+
stdin=subprocess.DEVNULL,
|
|
199
|
+
stdout=subprocess.PIPE,
|
|
200
|
+
stderr=subprocess.STDOUT,
|
|
201
|
+
text=True,
|
|
202
|
+
bufsize=1,
|
|
203
|
+
cwd=cwd,
|
|
204
|
+
env=env,
|
|
205
|
+
encoding=encoding,
|
|
206
|
+
errors=errors,
|
|
207
|
+
) as proc:
|
|
208
|
+
assert proc.stdout is not None # passing stdout=subprocess.PIPE guarantees this
|
|
188
209
|
|
|
189
210
|
for line in iter(proc.stdout.readline, ''):
|
|
190
211
|
line = line.removesuffix('\n')
|
|
@@ -196,8 +217,8 @@ def run(
|
|
|
196
217
|
print_output(line)
|
|
197
218
|
|
|
198
219
|
output += line + '\n'
|
|
199
|
-
if len(output)>max_output_size+1:
|
|
200
|
-
output = output[-max_output_size-1:]
|
|
220
|
+
if len(output) > max_output_size + 1:
|
|
221
|
+
output = output[-max_output_size - 1 :] # drop the beginning of the string
|
|
201
222
|
|
|
202
223
|
proc.wait()
|
|
203
224
|
result = RunResult(exit_code=proc.returncode, output=output.removesuffix('\n'))
|
|
@@ -215,7 +236,7 @@ def run(
|
|
|
215
236
|
return attempt_run()
|
|
216
237
|
except RunError as e:
|
|
217
238
|
print_message(str(e))
|
|
218
|
-
if attempts_left!=1:
|
|
239
|
+
if attempts_left != 1:
|
|
219
240
|
plural = 's'
|
|
220
241
|
else:
|
|
221
242
|
plural = ''
|
|
@@ -9,13 +9,16 @@ __all__ = [
|
|
|
9
9
|
'Success',
|
|
10
10
|
]
|
|
11
11
|
|
|
12
|
-
from collections.abc import Mapping
|
|
12
|
+
from collections.abc import Mapping
|
|
13
|
+
from collections.abc import Sequence
|
|
13
14
|
from pathlib import Path
|
|
14
|
-
from typing import Optional
|
|
15
|
+
from typing import Optional
|
|
16
|
+
from typing import TypedDict
|
|
15
17
|
|
|
16
18
|
import typeguard
|
|
17
19
|
from typing_extensions import Unpack
|
|
18
20
|
|
|
21
|
+
|
|
19
22
|
class AnyExitCode:
|
|
20
23
|
"""
|
|
21
24
|
Use an instance of this class (eg. fancy_subprocess.ANY_EXIT_CODE) as the 'success' argument to make run() and related functions treat any exit code as success.
|
|
@@ -23,12 +26,14 @@ class AnyExitCode:
|
|
|
23
26
|
|
|
24
27
|
pass
|
|
25
28
|
|
|
29
|
+
|
|
26
30
|
ANY_EXIT_CODE = AnyExitCode()
|
|
27
31
|
|
|
28
32
|
Success = Sequence[int] | AnyExitCode
|
|
29
33
|
|
|
30
34
|
EnvOverrides = Mapping[str, str]
|
|
31
35
|
|
|
36
|
+
|
|
32
37
|
class RunParams(TypedDict, total=False):
|
|
33
38
|
message_quiet: Optional[bool]
|
|
34
39
|
output_quiet: Optional[bool]
|
|
@@ -46,11 +51,14 @@ class RunParams(TypedDict, total=False):
|
|
|
46
51
|
errors: Optional[str]
|
|
47
52
|
replace_fffd_with_question_mark: Optional[bool]
|
|
48
53
|
|
|
54
|
+
|
|
49
55
|
def check_run_params(**kwargs: Unpack[RunParams]) -> None:
|
|
50
56
|
try:
|
|
51
57
|
typeguard.check_type(kwargs, RunParams, collection_check_strategy=typeguard.CollectionCheckStrategy.ALL_ITEMS)
|
|
52
58
|
except typeguard.TypeCheckError as e:
|
|
53
|
-
|
|
59
|
+
# we don't wanna expose the stacktrace from typeguard to be able to replace it with another library if needed
|
|
60
|
+
raise ValueError(str(e)) from None
|
|
61
|
+
|
|
54
62
|
|
|
55
63
|
def change_default_run_params(params: RunParams, **new_defaults: Unpack[RunParams]) -> None:
|
|
56
64
|
check_run_params(**params)
|
|
@@ -59,7 +67,8 @@ def change_default_run_params(params: RunParams, **new_defaults: Unpack[RunParam
|
|
|
59
67
|
for key in new_defaults.keys():
|
|
60
68
|
if params.get(key) is None:
|
|
61
69
|
# It's safe to ignore the TypedDict-related checks here because of the check_run_params() calls
|
|
62
|
-
params[key] = new_defaults[key]
|
|
70
|
+
params[key] = new_defaults[key] # type: ignore[literal-required] # ty: ignore[invalid-key]
|
|
71
|
+
|
|
63
72
|
|
|
64
73
|
def force_run_params(params: RunParams, **forced_values: Unpack[RunParams]) -> None:
|
|
65
74
|
check_run_params(**params)
|
|
@@ -70,4 +79,4 @@ def force_run_params(params: RunParams, **forced_values: Unpack[RunParams]) -> N
|
|
|
70
79
|
raise ValueError(f'Trying to override forced keyword parameter {key} is disallowed')
|
|
71
80
|
else:
|
|
72
81
|
# It's safe to ignore the TypedDict-related checks here because of the check_run_params() calls
|
|
73
|
-
params[key] = forced_values[key]
|
|
82
|
+
params[key] = forced_values[key] # type: ignore[literal-required] # ty: ignore[invalid-key]
|
|
@@ -9,10 +9,16 @@ from typing import Optional
|
|
|
9
9
|
|
|
10
10
|
from typing_extensions import Unpack
|
|
11
11
|
|
|
12
|
-
from fancy_subprocess._print import Indent
|
|
13
|
-
from fancy_subprocess.
|
|
14
|
-
from fancy_subprocess.
|
|
15
|
-
from fancy_subprocess.
|
|
12
|
+
from fancy_subprocess._print import Indent
|
|
13
|
+
from fancy_subprocess._print import PrintFunction
|
|
14
|
+
from fancy_subprocess._print import indented_print_factory
|
|
15
|
+
from fancy_subprocess._print import silenced_print
|
|
16
|
+
from fancy_subprocess._run_core import RunResult
|
|
17
|
+
from fancy_subprocess._run_core import run
|
|
18
|
+
from fancy_subprocess._run_param import RunParams
|
|
19
|
+
from fancy_subprocess._run_param import check_run_params
|
|
20
|
+
from fancy_subprocess._run_param import force_run_params
|
|
21
|
+
|
|
16
22
|
|
|
17
23
|
def run_silenced(
|
|
18
24
|
cmd: Sequence[str | Path],
|
|
@@ -42,6 +48,7 @@ def run_silenced(
|
|
|
42
48
|
**forwarded_args,
|
|
43
49
|
)
|
|
44
50
|
|
|
51
|
+
|
|
45
52
|
def run_indented(
|
|
46
53
|
cmd: Sequence[str | Path],
|
|
47
54
|
*,
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
__all__ = [
|
|
2
|
+
'value_or',
|
|
3
|
+
]
|
|
4
|
+
|
|
5
|
+
from collections.abc import Sequence
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
from typing import TypeVar
|
|
8
|
+
|
|
9
|
+
import oslex
|
|
10
|
+
|
|
11
|
+
T = TypeVar('T')
|
|
12
|
+
U = TypeVar('U')
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def value_or(value: T | None, default: U) -> T | U:
|
|
16
|
+
if value is None:
|
|
17
|
+
return default
|
|
18
|
+
else:
|
|
19
|
+
return value
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def oslex_join(cmd: Sequence[str | Path]) -> str:
|
|
23
|
+
return oslex.join([str(arg) for arg in cmd])
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "fancy-subprocess"
|
|
7
|
-
version = "2.
|
|
7
|
+
version = "2.4"
|
|
8
8
|
authors = [
|
|
9
9
|
{ name="Tamás PEREGI", email="petamas@gmail.com" },
|
|
10
10
|
]
|
|
@@ -17,6 +17,7 @@ classifiers = [
|
|
|
17
17
|
"Programming Language :: Python :: 3.11",
|
|
18
18
|
"Programming Language :: Python :: 3.12",
|
|
19
19
|
"Programming Language :: Python :: 3.13",
|
|
20
|
+
"Programming Language :: Python :: 3.14",
|
|
20
21
|
"License :: OSI Approved :: MIT License",
|
|
21
22
|
"Operating System :: OS Independent",
|
|
22
23
|
"Operating System :: MacOS",
|
|
@@ -26,7 +27,7 @@ classifiers = [
|
|
|
26
27
|
license = "MIT"
|
|
27
28
|
license-files = ["LICENSE"]
|
|
28
29
|
dependencies = [
|
|
29
|
-
"ntstatus>=
|
|
30
|
+
"ntstatus>=2.0,<3",
|
|
30
31
|
"oslex>=0.1.3,<2",
|
|
31
32
|
"pathext>=1.5,<2",
|
|
32
33
|
"typeguard>=4.4.2,<5",
|
|
@@ -36,3 +37,40 @@ dependencies = [
|
|
|
36
37
|
[project.urls]
|
|
37
38
|
"Homepage" = "https://github.com/petamas/python-fancy-subprocess"
|
|
38
39
|
"Bug Tracker" = "https://github.com/petamas/python-fancy-subprocess/issues"
|
|
40
|
+
|
|
41
|
+
[dependency-groups]
|
|
42
|
+
dev = [
|
|
43
|
+
"mypy>=1.14.1,<1.15",
|
|
44
|
+
"ruff>=0.15.12,<0.16",
|
|
45
|
+
"ty>=0.0.34,<0.1",
|
|
46
|
+
]
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
[tool.mypy]
|
|
50
|
+
strict = true
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
[tool.ruff]
|
|
54
|
+
line-length = 120
|
|
55
|
+
|
|
56
|
+
[tool.ruff.format]
|
|
57
|
+
quote-style = "single"
|
|
58
|
+
|
|
59
|
+
[tool.ruff.lint]
|
|
60
|
+
extend-select = [
|
|
61
|
+
"I", # isort
|
|
62
|
+
]
|
|
63
|
+
isort.force-single-line = true
|
|
64
|
+
|
|
65
|
+
[tool.ruff.lint.per-file-ignores]
|
|
66
|
+
# Allow star imports in __init__.py files
|
|
67
|
+
"__init__.py" = [
|
|
68
|
+
"F403", # undefined-local-with-import-star
|
|
69
|
+
"F405", # undefined-local-with-import-star-usage
|
|
70
|
+
]
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
[tool.ty]
|
|
74
|
+
rules.undefined-reveal = "ignore"
|
|
75
|
+
analysis.respect-type-ignore-comments = false
|
|
76
|
+
terminal.error-on-warning = true
|
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
version = 1
|
|
2
|
+
revision = 3
|
|
3
|
+
requires-python = ">=3.10"
|
|
4
|
+
|
|
5
|
+
[[package]]
|
|
6
|
+
name = "fancy-subprocess"
|
|
7
|
+
version = "2.4"
|
|
8
|
+
source = { editable = "." }
|
|
9
|
+
dependencies = [
|
|
10
|
+
{ name = "ntstatus" },
|
|
11
|
+
{ name = "oslex" },
|
|
12
|
+
{ name = "pathext" },
|
|
13
|
+
{ name = "typeguard" },
|
|
14
|
+
{ name = "typing-extensions" },
|
|
15
|
+
]
|
|
16
|
+
|
|
17
|
+
[package.dev-dependencies]
|
|
18
|
+
dev = [
|
|
19
|
+
{ name = "mypy" },
|
|
20
|
+
{ name = "ruff" },
|
|
21
|
+
{ name = "ty" },
|
|
22
|
+
]
|
|
23
|
+
|
|
24
|
+
[package.metadata]
|
|
25
|
+
requires-dist = [
|
|
26
|
+
{ name = "ntstatus", specifier = ">=2.0,<3" },
|
|
27
|
+
{ name = "oslex", specifier = ">=0.1.3,<2" },
|
|
28
|
+
{ name = "pathext", specifier = ">=1.5,<2" },
|
|
29
|
+
{ name = "typeguard", specifier = ">=4.4.2,<5" },
|
|
30
|
+
{ name = "typing-extensions", specifier = ">=4.14,<5" },
|
|
31
|
+
]
|
|
32
|
+
|
|
33
|
+
[package.metadata.requires-dev]
|
|
34
|
+
dev = [
|
|
35
|
+
{ name = "mypy", specifier = ">=1.14.1,<1.15" },
|
|
36
|
+
{ name = "ruff", specifier = ">=0.15.12,<0.16" },
|
|
37
|
+
{ name = "ty", specifier = ">=0.0.34,<0.1" },
|
|
38
|
+
]
|
|
39
|
+
|
|
40
|
+
[[package]]
|
|
41
|
+
name = "more-itertools"
|
|
42
|
+
version = "10.8.0"
|
|
43
|
+
source = { registry = "https://pypi.org/simple" }
|
|
44
|
+
sdist = { url = "https://files.pythonhosted.org/packages/ea/5d/38b681d3fce7a266dd9ab73c66959406d565b3e85f21d5e66e1181d93721/more_itertools-10.8.0.tar.gz", hash = "sha256:f638ddf8a1a0d134181275fb5d58b086ead7c6a72429ad725c67503f13ba30bd", size = 137431, upload-time = "2025-09-02T15:23:11.018Z" }
|
|
45
|
+
wheels = [
|
|
46
|
+
{ url = "https://files.pythonhosted.org/packages/a4/8e/469e5a4a2f5855992e425f3cb33804cc07bf18d48f2db061aec61ce50270/more_itertools-10.8.0-py3-none-any.whl", hash = "sha256:52d4362373dcf7c52546bc4af9a86ee7c4579df9a8dc268be0a2f949d376cc9b", size = 69667, upload-time = "2025-09-02T15:23:09.635Z" },
|
|
47
|
+
]
|
|
48
|
+
|
|
49
|
+
[[package]]
|
|
50
|
+
name = "mslex"
|
|
51
|
+
version = "1.3.0"
|
|
52
|
+
source = { registry = "https://pypi.org/simple" }
|
|
53
|
+
sdist = { url = "https://files.pythonhosted.org/packages/e0/97/7022667073c99a0fe028f2e34b9bf76b49a611afd21b02527fbfd92d4cd5/mslex-1.3.0.tar.gz", hash = "sha256:641c887d1d3db610eee2af37a8e5abda3f70b3006cdfd2d0d29dc0d1ae28a85d", size = 11583, upload-time = "2024-10-16T13:16:18.523Z" }
|
|
54
|
+
wheels = [
|
|
55
|
+
{ url = "https://files.pythonhosted.org/packages/64/f2/66bd65ca0139675a0d7b18f0bada6e12b51a984e41a76dbe44761bf1b3ee/mslex-1.3.0-py3-none-any.whl", hash = "sha256:c7074b347201b3466fc077c5692fbce9b5f62a63a51f537a53fbbd02eff2eea4", size = 7820, upload-time = "2024-10-16T13:16:17.566Z" },
|
|
56
|
+
]
|
|
57
|
+
|
|
58
|
+
[[package]]
|
|
59
|
+
name = "mypy"
|
|
60
|
+
version = "1.14.1"
|
|
61
|
+
source = { registry = "https://pypi.org/simple" }
|
|
62
|
+
dependencies = [
|
|
63
|
+
{ name = "mypy-extensions" },
|
|
64
|
+
{ name = "tomli", marker = "python_full_version < '3.11'" },
|
|
65
|
+
{ name = "typing-extensions" },
|
|
66
|
+
]
|
|
67
|
+
sdist = { url = "https://files.pythonhosted.org/packages/b9/eb/2c92d8ea1e684440f54fa49ac5d9a5f19967b7b472a281f419e69a8d228e/mypy-1.14.1.tar.gz", hash = "sha256:7ec88144fe9b510e8475ec2f5f251992690fcf89ccb4500b214b4226abcd32d6", size = 3216051, upload-time = "2024-12-30T16:39:07.335Z" }
|
|
68
|
+
wheels = [
|
|
69
|
+
{ url = "https://files.pythonhosted.org/packages/9b/7a/87ae2adb31d68402da6da1e5f30c07ea6063e9f09b5e7cfc9dfa44075e74/mypy-1.14.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:52686e37cf13d559f668aa398dd7ddf1f92c5d613e4f8cb262be2fb4fedb0fcb", size = 11211002, upload-time = "2024-12-30T16:37:22.435Z" },
|
|
70
|
+
{ url = "https://files.pythonhosted.org/packages/e1/23/eada4c38608b444618a132be0d199b280049ded278b24cbb9d3fc59658e4/mypy-1.14.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:1fb545ca340537d4b45d3eecdb3def05e913299ca72c290326be19b3804b39c0", size = 10358400, upload-time = "2024-12-30T16:37:53.526Z" },
|
|
71
|
+
{ url = "https://files.pythonhosted.org/packages/43/c9/d6785c6f66241c62fd2992b05057f404237deaad1566545e9f144ced07f5/mypy-1.14.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:90716d8b2d1f4cd503309788e51366f07c56635a3309b0f6a32547eaaa36a64d", size = 12095172, upload-time = "2024-12-30T16:37:50.332Z" },
|
|
72
|
+
{ url = "https://files.pythonhosted.org/packages/c3/62/daa7e787770c83c52ce2aaf1a111eae5893de9e004743f51bfcad9e487ec/mypy-1.14.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2ae753f5c9fef278bcf12e1a564351764f2a6da579d4a81347e1d5a15819997b", size = 12828732, upload-time = "2024-12-30T16:37:29.96Z" },
|
|
73
|
+
{ url = "https://files.pythonhosted.org/packages/1b/a2/5fb18318a3637f29f16f4e41340b795da14f4751ef4f51c99ff39ab62e52/mypy-1.14.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:e0fe0f5feaafcb04505bcf439e991c6d8f1bf8b15f12b05feeed96e9e7bf1427", size = 13012197, upload-time = "2024-12-30T16:38:05.037Z" },
|
|
74
|
+
{ url = "https://files.pythonhosted.org/packages/28/99/e153ce39105d164b5f02c06c35c7ba958aaff50a2babba7d080988b03fe7/mypy-1.14.1-cp310-cp310-win_amd64.whl", hash = "sha256:7d54bd85b925e501c555a3227f3ec0cfc54ee8b6930bd6141ec872d1c572f81f", size = 9780836, upload-time = "2024-12-30T16:37:19.726Z" },
|
|
75
|
+
{ url = "https://files.pythonhosted.org/packages/da/11/a9422850fd506edbcdc7f6090682ecceaf1f87b9dd847f9df79942da8506/mypy-1.14.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f995e511de847791c3b11ed90084a7a0aafdc074ab88c5a9711622fe4751138c", size = 11120432, upload-time = "2024-12-30T16:37:11.533Z" },
|
|
76
|
+
{ url = "https://files.pythonhosted.org/packages/b6/9e/47e450fd39078d9c02d620545b2cb37993a8a8bdf7db3652ace2f80521ca/mypy-1.14.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d64169ec3b8461311f8ce2fd2eb5d33e2d0f2c7b49116259c51d0d96edee48d1", size = 10279515, upload-time = "2024-12-30T16:37:40.724Z" },
|
|
77
|
+
{ url = "https://files.pythonhosted.org/packages/01/b5/6c8d33bd0f851a7692a8bfe4ee75eb82b6983a3cf39e5e32a5d2a723f0c1/mypy-1.14.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ba24549de7b89b6381b91fbc068d798192b1b5201987070319889e93038967a8", size = 12025791, upload-time = "2024-12-30T16:36:58.73Z" },
|
|
78
|
+
{ url = "https://files.pythonhosted.org/packages/f0/4c/e10e2c46ea37cab5c471d0ddaaa9a434dc1d28650078ac1b56c2d7b9b2e4/mypy-1.14.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:183cf0a45457d28ff9d758730cd0210419ac27d4d3f285beda038c9083363b1f", size = 12749203, upload-time = "2024-12-30T16:37:03.741Z" },
|
|
79
|
+
{ url = "https://files.pythonhosted.org/packages/88/55/beacb0c69beab2153a0f57671ec07861d27d735a0faff135a494cd4f5020/mypy-1.14.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f2a0ecc86378f45347f586e4163d1769dd81c5a223d577fe351f26b179e148b1", size = 12885900, upload-time = "2024-12-30T16:37:57.948Z" },
|
|
80
|
+
{ url = "https://files.pythonhosted.org/packages/a2/75/8c93ff7f315c4d086a2dfcde02f713004357d70a163eddb6c56a6a5eff40/mypy-1.14.1-cp311-cp311-win_amd64.whl", hash = "sha256:ad3301ebebec9e8ee7135d8e3109ca76c23752bac1e717bc84cd3836b4bf3eae", size = 9777869, upload-time = "2024-12-30T16:37:33.428Z" },
|
|
81
|
+
{ url = "https://files.pythonhosted.org/packages/43/1b/b38c079609bb4627905b74fc6a49849835acf68547ac33d8ceb707de5f52/mypy-1.14.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:30ff5ef8519bbc2e18b3b54521ec319513a26f1bba19a7582e7b1f58a6e69f14", size = 11266668, upload-time = "2024-12-30T16:38:02.211Z" },
|
|
82
|
+
{ url = "https://files.pythonhosted.org/packages/6b/75/2ed0d2964c1ffc9971c729f7a544e9cd34b2cdabbe2d11afd148d7838aa2/mypy-1.14.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:cb9f255c18052343c70234907e2e532bc7e55a62565d64536dbc7706a20b78b9", size = 10254060, upload-time = "2024-12-30T16:37:46.131Z" },
|
|
83
|
+
{ url = "https://files.pythonhosted.org/packages/a1/5f/7b8051552d4da3c51bbe8fcafffd76a6823779101a2b198d80886cd8f08e/mypy-1.14.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8b4e3413e0bddea671012b063e27591b953d653209e7a4fa5e48759cda77ca11", size = 11933167, upload-time = "2024-12-30T16:37:43.534Z" },
|
|
84
|
+
{ url = "https://files.pythonhosted.org/packages/04/90/f53971d3ac39d8b68bbaab9a4c6c58c8caa4d5fd3d587d16f5927eeeabe1/mypy-1.14.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:553c293b1fbdebb6c3c4030589dab9fafb6dfa768995a453d8a5d3b23784af2e", size = 12864341, upload-time = "2024-12-30T16:37:36.249Z" },
|
|
85
|
+
{ url = "https://files.pythonhosted.org/packages/03/d2/8bc0aeaaf2e88c977db41583559319f1821c069e943ada2701e86d0430b7/mypy-1.14.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:fad79bfe3b65fe6a1efaed97b445c3d37f7be9fdc348bdb2d7cac75579607c89", size = 12972991, upload-time = "2024-12-30T16:37:06.743Z" },
|
|
86
|
+
{ url = "https://files.pythonhosted.org/packages/6f/17/07815114b903b49b0f2cf7499f1c130e5aa459411596668267535fe9243c/mypy-1.14.1-cp312-cp312-win_amd64.whl", hash = "sha256:8fa2220e54d2946e94ab6dbb3ba0a992795bd68b16dc852db33028df2b00191b", size = 9879016, upload-time = "2024-12-30T16:37:15.02Z" },
|
|
87
|
+
{ url = "https://files.pythonhosted.org/packages/9e/15/bb6a686901f59222275ab228453de741185f9d54fecbaacec041679496c6/mypy-1.14.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:92c3ed5afb06c3a8e188cb5da4984cab9ec9a77ba956ee419c68a388b4595255", size = 11252097, upload-time = "2024-12-30T16:37:25.144Z" },
|
|
88
|
+
{ url = "https://files.pythonhosted.org/packages/f8/b3/8b0f74dfd072c802b7fa368829defdf3ee1566ba74c32a2cb2403f68024c/mypy-1.14.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:dbec574648b3e25f43d23577309b16534431db4ddc09fda50841f1e34e64ed34", size = 10239728, upload-time = "2024-12-30T16:38:08.634Z" },
|
|
89
|
+
{ url = "https://files.pythonhosted.org/packages/c5/9b/4fd95ab20c52bb5b8c03cc49169be5905d931de17edfe4d9d2986800b52e/mypy-1.14.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8c6d94b16d62eb3e947281aa7347d78236688e21081f11de976376cf010eb31a", size = 11924965, upload-time = "2024-12-30T16:38:12.132Z" },
|
|
90
|
+
{ url = "https://files.pythonhosted.org/packages/56/9d/4a236b9c57f5d8f08ed346914b3f091a62dd7e19336b2b2a0d85485f82ff/mypy-1.14.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d4b19b03fdf54f3c5b2fa474c56b4c13c9dbfb9a2db4370ede7ec11a2c5927d9", size = 12867660, upload-time = "2024-12-30T16:38:17.342Z" },
|
|
91
|
+
{ url = "https://files.pythonhosted.org/packages/40/88/a61a5497e2f68d9027de2bb139c7bb9abaeb1be1584649fa9d807f80a338/mypy-1.14.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:0c911fde686394753fff899c409fd4e16e9b294c24bfd5e1ea4675deae1ac6fd", size = 12969198, upload-time = "2024-12-30T16:38:32.839Z" },
|
|
92
|
+
{ url = "https://files.pythonhosted.org/packages/54/da/3d6fc5d92d324701b0c23fb413c853892bfe0e1dbe06c9138037d459756b/mypy-1.14.1-cp313-cp313-win_amd64.whl", hash = "sha256:8b21525cb51671219f5307be85f7e646a153e5acc656e5cebf64bfa076c50107", size = 9885276, upload-time = "2024-12-30T16:38:20.828Z" },
|
|
93
|
+
{ url = "https://files.pythonhosted.org/packages/a0/b5/32dd67b69a16d088e533962e5044e51004176a9952419de0370cdaead0f8/mypy-1.14.1-py3-none-any.whl", hash = "sha256:b66a60cc4073aeb8ae00057f9c1f64d49e90f918fbcef9a977eb121da8b8f1d1", size = 2752905, upload-time = "2024-12-30T16:38:42.021Z" },
|
|
94
|
+
]
|
|
95
|
+
|
|
96
|
+
[[package]]
|
|
97
|
+
name = "mypy-extensions"
|
|
98
|
+
version = "1.1.0"
|
|
99
|
+
source = { registry = "https://pypi.org/simple" }
|
|
100
|
+
sdist = { url = "https://files.pythonhosted.org/packages/a2/6e/371856a3fb9d31ca8dac321cda606860fa4548858c0cc45d9d1d4ca2628b/mypy_extensions-1.1.0.tar.gz", hash = "sha256:52e68efc3284861e772bbcd66823fde5ae21fd2fdb51c62a211403730b916558", size = 6343, upload-time = "2025-04-22T14:54:24.164Z" }
|
|
101
|
+
wheels = [
|
|
102
|
+
{ url = "https://files.pythonhosted.org/packages/79/7b/2c79738432f5c924bef5071f933bcc9efd0473bac3b4aa584a6f7c1c8df8/mypy_extensions-1.1.0-py3-none-any.whl", hash = "sha256:1be4cccdb0f2482337c4743e60421de3a356cd97508abadd57d47403e94f5505", size = 4963, upload-time = "2025-04-22T14:54:22.983Z" },
|
|
103
|
+
]
|
|
104
|
+
|
|
105
|
+
[[package]]
|
|
106
|
+
name = "ntstatus"
|
|
107
|
+
version = "2.0"
|
|
108
|
+
source = { registry = "https://pypi.org/simple" }
|
|
109
|
+
sdist = { url = "https://files.pythonhosted.org/packages/d1/5d/e1caf3dc856bf17421707d43db640b25c51547a045966d08460feb4eab32/ntstatus-2.0.tar.gz", hash = "sha256:b5956961d3e723ed2e429b1817d74ab925ef9eea523089a5dbcc59e3185e7c3d", size = 263733, upload-time = "2025-06-11T13:00:59.396Z" }
|
|
110
|
+
wheels = [
|
|
111
|
+
{ url = "https://files.pythonhosted.org/packages/18/39/b9608ead33d92d4ec7f8148744160c736efe625d18ff5f8d72068e79e93d/ntstatus-2.0-py3-none-any.whl", hash = "sha256:df4cecb8f6a4052ea01871f36c5445fb2e945e6ceee72c6369c1669e06de47d1", size = 260611, upload-time = "2025-06-11T13:00:58.038Z" },
|
|
112
|
+
]
|
|
113
|
+
|
|
114
|
+
[[package]]
|
|
115
|
+
name = "oslex"
|
|
116
|
+
version = "0.1.3"
|
|
117
|
+
source = { registry = "https://pypi.org/simple" }
|
|
118
|
+
dependencies = [
|
|
119
|
+
{ name = "mslex" },
|
|
120
|
+
]
|
|
121
|
+
sdist = { url = "https://files.pythonhosted.org/packages/5e/a9/ebd426ee0ca59fb5ba8f0039c53989f4ca475f2dd9583b5719e2fb01602c/oslex-0.1.3.tar.gz", hash = "sha256:1ed4cd82c75df2a8bcb0da34400984183753933155d0c7d999fa533137685f2d", size = 4415, upload-time = "2023-07-17T18:33:20.319Z" }
|
|
122
|
+
wheels = [
|
|
123
|
+
{ url = "https://files.pythonhosted.org/packages/8a/21/f9d1c6196533d5e43625a71244796d6ec2565318f2d91f6c10ec461222f1/oslex-0.1.3-py3-none-any.whl", hash = "sha256:71acb8a1d42ed78ddd213a1d3a628bbf837f758bd2999c91df7ce57972466bdf", size = 3546, upload-time = "2023-07-17T18:33:18.725Z" },
|
|
124
|
+
]
|
|
125
|
+
|
|
126
|
+
[[package]]
|
|
127
|
+
name = "pathext"
|
|
128
|
+
version = "1.5"
|
|
129
|
+
source = { registry = "https://pypi.org/simple" }
|
|
130
|
+
dependencies = [
|
|
131
|
+
{ name = "more-itertools" },
|
|
132
|
+
]
|
|
133
|
+
sdist = { url = "https://files.pythonhosted.org/packages/09/b3/cd7d7282c1640300630e963b84b6e202862206f5ac24959015d83372e16c/pathext-1.5.tar.gz", hash = "sha256:cbfd6f697a4874be7ea37109dbf60f108d451b44bb3df290f1560c75fa16bb87", size = 6424, upload-time = "2025-06-08T18:52:26.159Z" }
|
|
134
|
+
wheels = [
|
|
135
|
+
{ url = "https://files.pythonhosted.org/packages/d0/d0/aab254e2ba1e2a390261ef746c4129ef81b2d13289850380c5273026915d/pathext-1.5-py3-none-any.whl", hash = "sha256:3aedc261736dc714881676847dcc20ce2246b09d331ec09276b478477a469530", size = 7325, upload-time = "2025-06-08T18:52:24.718Z" },
|
|
136
|
+
]
|
|
137
|
+
|
|
138
|
+
[[package]]
|
|
139
|
+
name = "ruff"
|
|
140
|
+
version = "0.15.12"
|
|
141
|
+
source = { registry = "https://pypi.org/simple" }
|
|
142
|
+
sdist = { url = "https://files.pythonhosted.org/packages/99/43/3291f1cc9106f4c63bdce7a8d0df5047fe8422a75b091c16b5e9355e0b11/ruff-0.15.12.tar.gz", hash = "sha256:ecea26adb26b4232c0c2ca19ccbc0083a68344180bba2a600605538ce51a40a6", size = 4643852, upload-time = "2026-04-24T18:17:14.305Z" }
|
|
143
|
+
wheels = [
|
|
144
|
+
{ url = "https://files.pythonhosted.org/packages/c3/6e/e78ffb61d4686f3d96ba3df2c801161843746dcbcbb17a1e927d4829312b/ruff-0.15.12-py3-none-linux_armv6l.whl", hash = "sha256:f86f176e188e94d6bdbc09f09bfd9dc729059ad93d0e7390b5a73efe19f8861c", size = 10640713, upload-time = "2026-04-24T18:17:22.841Z" },
|
|
145
|
+
{ url = "https://files.pythonhosted.org/packages/ae/08/a317bc231fb9e7b93e4ef3089501e51922ff88d6936ce5cf870c4fe55419/ruff-0.15.12-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:e3bcd123364c3770b8e1b7baaf343cc99a35f197c5c6e8af79015c666c423a6c", size = 11069267, upload-time = "2026-04-24T18:17:30.105Z" },
|
|
146
|
+
{ url = "https://files.pythonhosted.org/packages/aa/a4/f828e9718d3dce1f5f11c39c4f65afd32783c8b2aebb2e3d259e492c47bd/ruff-0.15.12-py3-none-macosx_11_0_arm64.whl", hash = "sha256:fe87510d000220aa1ed530d4448a7c696a0cae1213e5ec30e5874287b66557b5", size = 10397182, upload-time = "2026-04-24T18:17:07.177Z" },
|
|
147
|
+
{ url = "https://files.pythonhosted.org/packages/71/e0/3310fc6d1b5e1fdea22bf3b1b807c7e187b581021b0d7d4514cccdb5fb71/ruff-0.15.12-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:84a1630093121375a3e2a95b4a6dc7b59e2b4ee76216e32d81aae550a832d002", size = 10758012, upload-time = "2026-04-24T18:16:55.759Z" },
|
|
148
|
+
{ url = "https://files.pythonhosted.org/packages/11/c1/a606911aee04c324ddaa883ae418f3569792fd3c4a10c50e0dd0a2311e1e/ruff-0.15.12-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fb129f40f114f089ebe0ca56c0d251cf2061b17651d464bb6478dc01e69f11f5", size = 10447479, upload-time = "2026-04-24T18:16:51.677Z" },
|
|
149
|
+
{ url = "https://files.pythonhosted.org/packages/9d/68/4201e8444f0894f21ab4aeeaee68aa4f10b51613514a20d80bd628d57e88/ruff-0.15.12-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b0c862b172d695db7598426b8af465e7e9ac00a3ea2a3630ee67eb82e366aaa6", size = 11234040, upload-time = "2026-04-24T18:17:16.529Z" },
|
|
150
|
+
{ url = "https://files.pythonhosted.org/packages/34/ff/8a6d6cf4ccc23fd67060874e832c18919d1557a0611ebef03fdb01fff11e/ruff-0.15.12-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2849ea9f3484c3aca43a82f484210370319e7170df4dfe4843395ddf6c57bc33", size = 12087377, upload-time = "2026-04-24T18:17:04.944Z" },
|
|
151
|
+
{ url = "https://files.pythonhosted.org/packages/85/f6/c669cf73f5152f623d34e69866a46d5e6185816b19fcd5b6dd8a2d299922/ruff-0.15.12-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9e77c7e51c07fe396826d5969a5b846d9cd4c402535835fb6e21ce8b28fef847", size = 11367784, upload-time = "2026-04-24T18:17:25.409Z" },
|
|
152
|
+
{ url = "https://files.pythonhosted.org/packages/e8/39/c61d193b8a1daaa8977f7dea9e8d8ba866e02ea7b65d32f6861693aa4c12/ruff-0.15.12-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:83b2f4f2f3b1026b5fb449b467d9264bf22067b600f7b6f41fc5958909f449d0", size = 11344088, upload-time = "2026-04-24T18:17:12.258Z" },
|
|
153
|
+
{ url = "https://files.pythonhosted.org/packages/c2/8d/49afab3645e31e12c590acb6d3b5b69d7aab5b81926dbaf7461f9441f37a/ruff-0.15.12-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:9ba3b8f1afd7e2e43d8943e55f249e13f9682fde09711644a6e7290eb4f3e339", size = 11271770, upload-time = "2026-04-24T18:17:02.457Z" },
|
|
154
|
+
{ url = "https://files.pythonhosted.org/packages/46/06/33f41fe94403e2b755481cdfb9b7ef3e4e0ed031c4581124658d935d52b4/ruff-0.15.12-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:e852ba9fdc890655e1d78f2df1499efbe0e54126bd405362154a75e2bde159c5", size = 10719355, upload-time = "2026-04-24T18:17:27.648Z" },
|
|
155
|
+
{ url = "https://files.pythonhosted.org/packages/0d/59/18aa4e014debbf559670e4048e39260a85c7fcee84acfd761ac01e7b8d35/ruff-0.15.12-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:dd8aed930da53780d22fc70bdf84452c843cf64f8cb4eb38984319c24c5cd5fd", size = 10462758, upload-time = "2026-04-24T18:17:32.347Z" },
|
|
156
|
+
{ url = "https://files.pythonhosted.org/packages/25/e7/cc9f16fd0f3b5fddcbd7ec3d6ae30c8f3fde1047f32a4093a98d633c6570/ruff-0.15.12-py3-none-musllinux_1_2_i686.whl", hash = "sha256:01da3988d225628b709493d7dc67c3b9b12c0210016b08690ef9bd27970b262b", size = 10953498, upload-time = "2026-04-24T18:17:20.674Z" },
|
|
157
|
+
{ url = "https://files.pythonhosted.org/packages/72/7a/a9ba7f98c7a575978698f4230c5e8cc54bbc761af34f560818f933dafa0c/ruff-0.15.12-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:9cae0f92bd5700d1213188b31cd3bdd2b315361296d10b96b8e2337d3d11f53e", size = 11447765, upload-time = "2026-04-24T18:17:09.755Z" },
|
|
158
|
+
{ url = "https://files.pythonhosted.org/packages/ea/f9/0ae446942c846b8266059ad8a30702a35afae55f5cdc54c5adf8d7afdc27/ruff-0.15.12-py3-none-win32.whl", hash = "sha256:d0185894e038d7043ba8fd6aee7499ece6462dc0ea9f1e260c7451807c714c20", size = 10657277, upload-time = "2026-04-24T18:17:18.591Z" },
|
|
159
|
+
{ url = "https://files.pythonhosted.org/packages/33/f1/9614e03e1cdcbf9437570b5400ced8a720b5db22b28d8e0f1bda429f660d/ruff-0.15.12-py3-none-win_amd64.whl", hash = "sha256:c87a162d61ab3adca47c03f7f717c68672edec7d1b5499e652331780fe74950d", size = 11837758, upload-time = "2026-04-24T18:17:00.113Z" },
|
|
160
|
+
{ url = "https://files.pythonhosted.org/packages/c0/98/6beb4b351e472e5f4c4613f7c35a5290b8be2497e183825310c4c3a3984b/ruff-0.15.12-py3-none-win_arm64.whl", hash = "sha256:a538f7a82d061cee7be55542aca1d86d1393d55d81d4fcc314370f4340930d4f", size = 11120821, upload-time = "2026-04-24T18:16:57.979Z" },
|
|
161
|
+
]
|
|
162
|
+
|
|
163
|
+
[[package]]
|
|
164
|
+
name = "tomli"
|
|
165
|
+
version = "2.4.1"
|
|
166
|
+
source = { registry = "https://pypi.org/simple" }
|
|
167
|
+
sdist = { url = "https://files.pythonhosted.org/packages/22/de/48c59722572767841493b26183a0d1cc411d54fd759c5607c4590b6563a6/tomli-2.4.1.tar.gz", hash = "sha256:7c7e1a961a0b2f2472c1ac5b69affa0ae1132c39adcb67aba98568702b9cc23f", size = 17543, upload-time = "2026-03-25T20:22:03.828Z" }
|
|
168
|
+
wheels = [
|
|
169
|
+
{ url = "https://files.pythonhosted.org/packages/f4/11/db3d5885d8528263d8adc260bb2d28ebf1270b96e98f0e0268d32b8d9900/tomli-2.4.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f8f0fc26ec2cc2b965b7a3b87cd19c5c6b8c5e5f436b984e85f486d652285c30", size = 154704, upload-time = "2026-03-25T20:21:10.473Z" },
|
|
170
|
+
{ url = "https://files.pythonhosted.org/packages/6d/f7/675db52c7e46064a9aa928885a9b20f4124ecb9bc2e1ce74c9106648d202/tomli-2.4.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4ab97e64ccda8756376892c53a72bd1f964e519c77236368527f758fbc36a53a", size = 149454, upload-time = "2026-03-25T20:21:12.036Z" },
|
|
171
|
+
{ url = "https://files.pythonhosted.org/packages/61/71/81c50943cf953efa35bce7646caab3cf457a7d8c030b27cfb40d7235f9ee/tomli-2.4.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:96481a5786729fd470164b47cdb3e0e58062a496f455ee41b4403be77cb5a076", size = 237561, upload-time = "2026-03-25T20:21:13.098Z" },
|
|
172
|
+
{ url = "https://files.pythonhosted.org/packages/48/c1/f41d9cb618acccca7df82aaf682f9b49013c9397212cb9f53219e3abac37/tomli-2.4.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5a881ab208c0baf688221f8cecc5401bd291d67e38a1ac884d6736cbcd8247e9", size = 243824, upload-time = "2026-03-25T20:21:14.569Z" },
|
|
173
|
+
{ url = "https://files.pythonhosted.org/packages/22/e4/5a816ecdd1f8ca51fb756ef684b90f2780afc52fc67f987e3c61d800a46d/tomli-2.4.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:47149d5bd38761ac8be13a84864bf0b7b70bc051806bc3669ab1cbc56216b23c", size = 242227, upload-time = "2026-03-25T20:21:15.712Z" },
|
|
174
|
+
{ url = "https://files.pythonhosted.org/packages/6b/49/2b2a0ef529aa6eec245d25f0c703e020a73955ad7edf73e7f54ddc608aa5/tomli-2.4.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ec9bfaf3ad2df51ace80688143a6a4ebc09a248f6ff781a9945e51937008fcbc", size = 247859, upload-time = "2026-03-25T20:21:17.001Z" },
|
|
175
|
+
{ url = "https://files.pythonhosted.org/packages/83/bd/6c1a630eaca337e1e78c5903104f831bda934c426f9231429396ce3c3467/tomli-2.4.1-cp311-cp311-win32.whl", hash = "sha256:ff2983983d34813c1aeb0fa89091e76c3a22889ee83ab27c5eeb45100560c049", size = 97204, upload-time = "2026-03-25T20:21:18.079Z" },
|
|
176
|
+
{ url = "https://files.pythonhosted.org/packages/42/59/71461df1a885647e10b6bb7802d0b8e66480c61f3f43079e0dcd315b3954/tomli-2.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:5ee18d9ebdb417e384b58fe414e8d6af9f4e7a0ae761519fb50f721de398dd4e", size = 108084, upload-time = "2026-03-25T20:21:18.978Z" },
|
|
177
|
+
{ url = "https://files.pythonhosted.org/packages/b8/83/dceca96142499c069475b790e7913b1044c1a4337e700751f48ed723f883/tomli-2.4.1-cp311-cp311-win_arm64.whl", hash = "sha256:c2541745709bad0264b7d4705ad453b76ccd191e64aa6f0fc66b69a293a45ece", size = 95285, upload-time = "2026-03-25T20:21:20.309Z" },
|
|
178
|
+
{ url = "https://files.pythonhosted.org/packages/c1/ba/42f134a3fe2b370f555f44b1d72feebb94debcab01676bf918d0cb70e9aa/tomli-2.4.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:c742f741d58a28940ce01d58f0ab2ea3ced8b12402f162f4d534dfe18ba1cd6a", size = 155924, upload-time = "2026-03-25T20:21:21.626Z" },
|
|
179
|
+
{ url = "https://files.pythonhosted.org/packages/dc/c7/62d7a17c26487ade21c5422b646110f2162f1fcc95980ef7f63e73c68f14/tomli-2.4.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7f86fd587c4ed9dd76f318225e7d9b29cfc5a9d43de44e5754db8d1128487085", size = 150018, upload-time = "2026-03-25T20:21:23.002Z" },
|
|
180
|
+
{ url = "https://files.pythonhosted.org/packages/5c/05/79d13d7c15f13bdef410bdd49a6485b1c37d28968314eabee452c22a7fda/tomli-2.4.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ff18e6a727ee0ab0388507b89d1bc6a22b138d1e2fa56d1ad494586d61d2eae9", size = 244948, upload-time = "2026-03-25T20:21:24.04Z" },
|
|
181
|
+
{ url = "https://files.pythonhosted.org/packages/10/90/d62ce007a1c80d0b2c93e02cab211224756240884751b94ca72df8a875ca/tomli-2.4.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:136443dbd7e1dee43c68ac2694fde36b2849865fa258d39bf822c10e8068eac5", size = 253341, upload-time = "2026-03-25T20:21:25.177Z" },
|
|
182
|
+
{ url = "https://files.pythonhosted.org/packages/1a/7e/caf6496d60152ad4ed09282c1885cca4eea150bfd007da84aea07bcc0a3e/tomli-2.4.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:5e262d41726bc187e69af7825504c933b6794dc3fbd5945e41a79bb14c31f585", size = 248159, upload-time = "2026-03-25T20:21:26.364Z" },
|
|
183
|
+
{ url = "https://files.pythonhosted.org/packages/99/e7/c6f69c3120de34bbd882c6fba7975f3d7a746e9218e56ab46a1bc4b42552/tomli-2.4.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:5cb41aa38891e073ee49d55fbc7839cfdb2bc0e600add13874d048c94aadddd1", size = 253290, upload-time = "2026-03-25T20:21:27.46Z" },
|
|
184
|
+
{ url = "https://files.pythonhosted.org/packages/d6/2f/4a3c322f22c5c66c4b836ec58211641a4067364f5dcdd7b974b4c5da300c/tomli-2.4.1-cp312-cp312-win32.whl", hash = "sha256:da25dc3563bff5965356133435b757a795a17b17d01dbc0f42fb32447ddfd917", size = 98141, upload-time = "2026-03-25T20:21:28.492Z" },
|
|
185
|
+
{ url = "https://files.pythonhosted.org/packages/24/22/4daacd05391b92c55759d55eaee21e1dfaea86ce5c571f10083360adf534/tomli-2.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:52c8ef851d9a240f11a88c003eacb03c31fc1c9c4ec64a99a0f922b93874fda9", size = 108847, upload-time = "2026-03-25T20:21:29.386Z" },
|
|
186
|
+
{ url = "https://files.pythonhosted.org/packages/68/fd/70e768887666ddd9e9f5d85129e84910f2db2796f9096aa02b721a53098d/tomli-2.4.1-cp312-cp312-win_arm64.whl", hash = "sha256:f758f1b9299d059cc3f6546ae2af89670cb1c4d48ea29c3cacc4fe7de3058257", size = 95088, upload-time = "2026-03-25T20:21:30.677Z" },
|
|
187
|
+
{ url = "https://files.pythonhosted.org/packages/07/06/b823a7e818c756d9a7123ba2cda7d07bc2dd32835648d1a7b7b7a05d848d/tomli-2.4.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:36d2bd2ad5fb9eaddba5226aa02c8ec3fa4f192631e347b3ed28186d43be6b54", size = 155866, upload-time = "2026-03-25T20:21:31.65Z" },
|
|
188
|
+
{ url = "https://files.pythonhosted.org/packages/14/6f/12645cf7f08e1a20c7eb8c297c6f11d31c1b50f316a7e7e1e1de6e2e7b7e/tomli-2.4.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:eb0dc4e38e6a1fd579e5d50369aa2e10acfc9cace504579b2faabb478e76941a", size = 149887, upload-time = "2026-03-25T20:21:33.028Z" },
|
|
189
|
+
{ url = "https://files.pythonhosted.org/packages/5c/e0/90637574e5e7212c09099c67ad349b04ec4d6020324539297b634a0192b0/tomli-2.4.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c7f2c7f2b9ca6bdeef8f0fa897f8e05085923eb091721675170254cbc5b02897", size = 243704, upload-time = "2026-03-25T20:21:34.51Z" },
|
|
190
|
+
{ url = "https://files.pythonhosted.org/packages/10/8f/d3ddb16c5a4befdf31a23307f72828686ab2096f068eaf56631e136c1fdd/tomli-2.4.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f3c6818a1a86dd6dca7ddcaaf76947d5ba31aecc28cb1b67009a5877c9a64f3f", size = 251628, upload-time = "2026-03-25T20:21:36.012Z" },
|
|
191
|
+
{ url = "https://files.pythonhosted.org/packages/e3/f1/dbeeb9116715abee2485bf0a12d07a8f31af94d71608c171c45f64c0469d/tomli-2.4.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:d312ef37c91508b0ab2cee7da26ec0b3ed2f03ce12bd87a588d771ae15dcf82d", size = 247180, upload-time = "2026-03-25T20:21:37.136Z" },
|
|
192
|
+
{ url = "https://files.pythonhosted.org/packages/d3/74/16336ffd19ed4da28a70959f92f506233bd7cfc2332b20bdb01591e8b1d1/tomli-2.4.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:51529d40e3ca50046d7606fa99ce3956a617f9b36380da3b7f0dd3dd28e68cb5", size = 251674, upload-time = "2026-03-25T20:21:38.298Z" },
|
|
193
|
+
{ url = "https://files.pythonhosted.org/packages/16/f9/229fa3434c590ddf6c0aa9af64d3af4b752540686cace29e6281e3458469/tomli-2.4.1-cp313-cp313-win32.whl", hash = "sha256:2190f2e9dd7508d2a90ded5ed369255980a1bcdd58e52f7fe24b8162bf9fedbd", size = 97976, upload-time = "2026-03-25T20:21:39.316Z" },
|
|
194
|
+
{ url = "https://files.pythonhosted.org/packages/6a/1e/71dfd96bcc1c775420cb8befe7a9d35f2e5b1309798f009dca17b7708c1e/tomli-2.4.1-cp313-cp313-win_amd64.whl", hash = "sha256:8d65a2fbf9d2f8352685bc1364177ee3923d6baf5e7f43ea4959d7d8bc326a36", size = 108755, upload-time = "2026-03-25T20:21:40.248Z" },
|
|
195
|
+
{ url = "https://files.pythonhosted.org/packages/83/7a/d34f422a021d62420b78f5c538e5b102f62bea616d1d75a13f0a88acb04a/tomli-2.4.1-cp313-cp313-win_arm64.whl", hash = "sha256:4b605484e43cdc43f0954ddae319fb75f04cc10dd80d830540060ee7cd0243cd", size = 95265, upload-time = "2026-03-25T20:21:41.219Z" },
|
|
196
|
+
{ url = "https://files.pythonhosted.org/packages/3c/fb/9a5c8d27dbab540869f7c1f8eb0abb3244189ce780ba9cd73f3770662072/tomli-2.4.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:fd0409a3653af6c147209d267a0e4243f0ae46b011aa978b1080359fddc9b6cf", size = 155726, upload-time = "2026-03-25T20:21:42.23Z" },
|
|
197
|
+
{ url = "https://files.pythonhosted.org/packages/62/05/d2f816630cc771ad836af54f5001f47a6f611d2d39535364f148b6a92d6b/tomli-2.4.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:a120733b01c45e9a0c34aeef92bf0cf1d56cfe81ed9d47d562f9ed591a9828ac", size = 149859, upload-time = "2026-03-25T20:21:43.386Z" },
|
|
198
|
+
{ url = "https://files.pythonhosted.org/packages/ce/48/66341bdb858ad9bd0ceab5a86f90eddab127cf8b046418009f2125630ecb/tomli-2.4.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:559db847dc486944896521f68d8190be1c9e719fced785720d2216fe7022b662", size = 244713, upload-time = "2026-03-25T20:21:44.474Z" },
|
|
199
|
+
{ url = "https://files.pythonhosted.org/packages/df/6d/c5fad00d82b3c7a3ab6189bd4b10e60466f22cfe8a08a9394185c8a8111c/tomli-2.4.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:01f520d4f53ef97964a240a035ec2a869fe1a37dde002b57ebc4417a27ccd853", size = 252084, upload-time = "2026-03-25T20:21:45.62Z" },
|
|
200
|
+
{ url = "https://files.pythonhosted.org/packages/00/71/3a69e86f3eafe8c7a59d008d245888051005bd657760e96d5fbfb0b740c2/tomli-2.4.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7f94b27a62cfad8496c8d2513e1a222dd446f095fca8987fceef261225538a15", size = 247973, upload-time = "2026-03-25T20:21:46.937Z" },
|
|
201
|
+
{ url = "https://files.pythonhosted.org/packages/67/50/361e986652847fec4bd5e4a0208752fbe64689c603c7ae5ea7cb16b1c0ca/tomli-2.4.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:ede3e6487c5ef5d28634ba3f31f989030ad6af71edfb0055cbbd14189ff240ba", size = 256223, upload-time = "2026-03-25T20:21:48.467Z" },
|
|
202
|
+
{ url = "https://files.pythonhosted.org/packages/8c/9a/b4173689a9203472e5467217e0154b00e260621caa227b6fa01feab16998/tomli-2.4.1-cp314-cp314-win32.whl", hash = "sha256:3d48a93ee1c9b79c04bb38772ee1b64dcf18ff43085896ea460ca8dec96f35f6", size = 98973, upload-time = "2026-03-25T20:21:49.526Z" },
|
|
203
|
+
{ url = "https://files.pythonhosted.org/packages/14/58/640ac93bf230cd27d002462c9af0d837779f8773bc03dee06b5835208214/tomli-2.4.1-cp314-cp314-win_amd64.whl", hash = "sha256:88dceee75c2c63af144e456745e10101eb67361050196b0b6af5d717254dddf7", size = 109082, upload-time = "2026-03-25T20:21:50.506Z" },
|
|
204
|
+
{ url = "https://files.pythonhosted.org/packages/d5/2f/702d5e05b227401c1068f0d386d79a589bb12bf64c3d2c72ce0631e3bc49/tomli-2.4.1-cp314-cp314-win_arm64.whl", hash = "sha256:b8c198f8c1805dc42708689ed6864951fd2494f924149d3e4bce7710f8eb5232", size = 96490, upload-time = "2026-03-25T20:21:51.474Z" },
|
|
205
|
+
{ url = "https://files.pythonhosted.org/packages/45/4b/b877b05c8ba62927d9865dd980e34a755de541eb65fffba52b4cc495d4d2/tomli-2.4.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:d4d8fe59808a54658fcc0160ecfb1b30f9089906c50b23bcb4c69eddc19ec2b4", size = 164263, upload-time = "2026-03-25T20:21:52.543Z" },
|
|
206
|
+
{ url = "https://files.pythonhosted.org/packages/24/79/6ab420d37a270b89f7195dec5448f79400d9e9c1826df982f3f8e97b24fd/tomli-2.4.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:7008df2e7655c495dd12d2a4ad038ff878d4ca4b81fccaf82b714e07eae4402c", size = 160736, upload-time = "2026-03-25T20:21:53.674Z" },
|
|
207
|
+
{ url = "https://files.pythonhosted.org/packages/02/e0/3630057d8eb170310785723ed5adcdfb7d50cb7e6455f85ba8a3deed642b/tomli-2.4.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1d8591993e228b0c930c4bb0db464bdad97b3289fb981255d6c9a41aedc84b2d", size = 270717, upload-time = "2026-03-25T20:21:55.129Z" },
|
|
208
|
+
{ url = "https://files.pythonhosted.org/packages/7a/b4/1613716072e544d1a7891f548d8f9ec6ce2faf42ca65acae01d76ea06bb0/tomli-2.4.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:734e20b57ba95624ecf1841e72b53f6e186355e216e5412de414e3c51e5e3c41", size = 278461, upload-time = "2026-03-25T20:21:56.228Z" },
|
|
209
|
+
{ url = "https://files.pythonhosted.org/packages/05/38/30f541baf6a3f6df77b3df16b01ba319221389e2da59427e221ef417ac0c/tomli-2.4.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:8a650c2dbafa08d42e51ba0b62740dae4ecb9338eefa093aa5c78ceb546fcd5c", size = 274855, upload-time = "2026-03-25T20:21:57.653Z" },
|
|
210
|
+
{ url = "https://files.pythonhosted.org/packages/77/a3/ec9dd4fd2c38e98de34223b995a3b34813e6bdadf86c75314c928350ed14/tomli-2.4.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:504aa796fe0569bb43171066009ead363de03675276d2d121ac1a4572397870f", size = 283144, upload-time = "2026-03-25T20:21:59.089Z" },
|
|
211
|
+
{ url = "https://files.pythonhosted.org/packages/ef/be/605a6261cac79fba2ec0c9827e986e00323a1945700969b8ee0b30d85453/tomli-2.4.1-cp314-cp314t-win32.whl", hash = "sha256:b1d22e6e9387bf4739fbe23bfa80e93f6b0373a7f1b96c6227c32bef95a4d7a8", size = 108683, upload-time = "2026-03-25T20:22:00.214Z" },
|
|
212
|
+
{ url = "https://files.pythonhosted.org/packages/12/64/da524626d3b9cc40c168a13da8335fe1c51be12c0a63685cc6db7308daae/tomli-2.4.1-cp314-cp314t-win_amd64.whl", hash = "sha256:2c1c351919aca02858f740c6d33adea0c5deea37f9ecca1cc1ef9e884a619d26", size = 121196, upload-time = "2026-03-25T20:22:01.169Z" },
|
|
213
|
+
{ url = "https://files.pythonhosted.org/packages/5a/cd/e80b62269fc78fc36c9af5a6b89c835baa8af28ff5ad28c7028d60860320/tomli-2.4.1-cp314-cp314t-win_arm64.whl", hash = "sha256:eab21f45c7f66c13f2a9e0e1535309cee140182a9cdae1e041d02e47291e8396", size = 100393, upload-time = "2026-03-25T20:22:02.137Z" },
|
|
214
|
+
{ url = "https://files.pythonhosted.org/packages/7b/61/cceae43728b7de99d9b847560c262873a1f6c98202171fd5ed62640b494b/tomli-2.4.1-py3-none-any.whl", hash = "sha256:0d85819802132122da43cb86656f8d1f8c6587d54ae7dcaf30e90533028b49fe", size = 14583, upload-time = "2026-03-25T20:22:03.012Z" },
|
|
215
|
+
]
|
|
216
|
+
|
|
217
|
+
[[package]]
|
|
218
|
+
name = "ty"
|
|
219
|
+
version = "0.0.35"
|
|
220
|
+
source = { registry = "https://pypi.org/simple" }
|
|
221
|
+
sdist = { url = "https://files.pythonhosted.org/packages/4e/53/440e7b1212c4b0abbd4adb7aed93f4971aa1f8dca386ac5515930afa9172/ty-0.0.35.tar.gz", hash = "sha256:8375c240ab38138a19db07996c9808fb7a92047c1492e1ce587c2ef5112ad3a9", size = 5629237, upload-time = "2026-05-10T18:25:17.105Z" }
|
|
222
|
+
wheels = [
|
|
223
|
+
{ url = "https://files.pythonhosted.org/packages/d4/84/19662ee881675815b7fafff940a365be1985730465afd9b75cb2edd5f8b3/ty-0.0.35-py3-none-linux_armv6l.whl", hash = "sha256:85ae1e59b9fb0b40e9d84fe61b29653c5f2f5e78b487ece371a7a38c20c781cf", size = 11198741, upload-time = "2026-05-10T18:24:49.378Z" },
|
|
224
|
+
{ url = "https://files.pythonhosted.org/packages/62/df/7e5b6f83d85b4d2e5b72b5dceb388f440acc10679417bd46f829b9200fab/ty-0.0.35-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:709dbb7af4fcadb1196863c00b8791bbbbcc9dacbe15a0ff17f0af82b35d415b", size = 10948304, upload-time = "2026-05-10T18:24:58.246Z" },
|
|
225
|
+
{ url = "https://files.pythonhosted.org/packages/59/94/72d7263aca055cde427f0ebcf08d6a74e5a5fee1d1e7fdd553696089cecb/ty-0.0.35-py3-none-macosx_11_0_arm64.whl", hash = "sha256:2cb0877419ab0c8708b6925cb0c2800b263842bd3c425113f200538772f3a0cc", size = 10407413, upload-time = "2026-05-10T18:24:37.422Z" },
|
|
226
|
+
{ url = "https://files.pythonhosted.org/packages/b6/23/fda6fae8a81ce0cb5f24cdfe63260e110c7af8844e31fa07d1e6e8ef0232/ty-0.0.35-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e7afbcfc61904b7e82e7fe1a1db832a40d8f01e69dee1775f6594e552980536c", size = 10932614, upload-time = "2026-05-10T18:24:47.401Z" },
|
|
227
|
+
{ url = "https://files.pythonhosted.org/packages/72/3d/b98d8d4aa1a5ed6daaf15864e838f605ca7b1e8b93b7e17b96ed4bc4dfed/ty-0.0.35-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b61498cc3e4178031c079951257fbdb209a891b4feb10ad6c40f615a51846f41", size = 10962982, upload-time = "2026-05-10T18:24:44.88Z" },
|
|
228
|
+
{ url = "https://files.pythonhosted.org/packages/18/c4/2881aad71bf6fb2f8df17fc8e4bc89e904e54490a3ee747b5ef73f98ac85/ty-0.0.35-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:573b1eacda349fc8dba0d767b41631c3a6f66412363127c5bf2b1b40a1d898d2", size = 11476274, upload-time = "2026-05-10T18:24:42.4Z" },
|
|
229
|
+
{ url = "https://files.pythonhosted.org/packages/34/0f/7717650adaeaddd23eea70470e2c26d3f0b9b18fdc7f26ec9552d6001f17/ty-0.0.35-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a7209746158d6393c1040aa64b3ca29622e212ea7d8bae22ba50dbcbb4f96f0a", size = 12012027, upload-time = "2026-05-10T18:25:00.752Z" },
|
|
230
|
+
{ url = "https://files.pythonhosted.org/packages/22/c9/1a16cb4aab6f4707d8f550772e91abc26d1c8870f19b5e2453ad10bb8209/ty-0.0.35-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4466a1470aa4418d49a9aa45d9da7de42033addd0a2837c5b2b0eb71d3c2bcd3", size = 11648894, upload-time = "2026-05-10T18:25:12.44Z" },
|
|
231
|
+
{ url = "https://files.pythonhosted.org/packages/18/a1/a977c0e07e9f88db9c67f90c6342a4dc4422c8091fa07bf26521870687c5/ty-0.0.35-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eb44bb742d52c309dcaa6598bcf4d82eb4bf1241b9e4940461e522e30093fe8b", size = 11560482, upload-time = "2026-05-10T18:25:05.172Z" },
|
|
232
|
+
{ url = "https://files.pythonhosted.org/packages/d6/c1/a5fb11227d5cc4ac3f29a115d8c8bc817578e8ef6907d1e4c914ddbf45ee/ty-0.0.35-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:34b219250736c989b2670a03782c61315f523f3a2be37f1f90b1207e2212c188", size = 11718495, upload-time = "2026-05-10T18:24:54.12Z" },
|
|
233
|
+
{ url = "https://files.pythonhosted.org/packages/3c/cb/e92e4317388b6d1fd821a46941b448a8a1ff0bf13e22147c5167d8fa1b00/ty-0.0.35-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:88e2ac497decc0940ef1a07571dee8a746112a93a09cdc7f8bca0099752e2e05", size = 10900815, upload-time = "2026-05-10T18:25:02.941Z" },
|
|
234
|
+
{ url = "https://files.pythonhosted.org/packages/e9/4f/03bd87388a92567f262f35ac64e10d2be047d258f2dfcf1405f500fa2b90/ty-0.0.35-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:02cae51b53e6ec17d5d827ff1a3a76fd119705b56a92156e04399eda6e911596", size = 10998051, upload-time = "2026-05-10T18:25:14.68Z" },
|
|
235
|
+
{ url = "https://files.pythonhosted.org/packages/b4/60/6edbc375ee6073973200096168f644e1081e5e55a7d42596826465b275de/ty-0.0.35-py3-none-musllinux_1_2_i686.whl", hash = "sha256:11871d730c9400d899ac0b9f3d660ed2e7e433377c8725549f8250a36a7f2620", size = 11148910, upload-time = "2026-05-10T18:24:51.842Z" },
|
|
236
|
+
{ url = "https://files.pythonhosted.org/packages/4d/b1/a845d2066ed521c477450f436d4bd353d107e7c02dd6536a485944aaf892/ty-0.0.35-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:1ad0a2f0530d0933dcc99ad36ac556c63e384ea72ab9a18d23ad2e2c9fd61c73", size = 11671005, upload-time = "2026-05-10T18:24:56.223Z" },
|
|
237
|
+
{ url = "https://files.pythonhosted.org/packages/73/81/1d5912a54fb66b2f95ac828ae61d422ef5afeae1263e4d231e40796c229f/ty-0.0.35-py3-none-win32.whl", hash = "sha256:0e25d63ec4ab116e7f6757e44d16ca9216bca679d19ecc36d119cf80faada61a", size = 10481096, upload-time = "2026-05-10T18:24:39.976Z" },
|
|
238
|
+
{ url = "https://files.pythonhosted.org/packages/3b/36/1c7f8632bfec1c321f01581d4c940a3617b24bd3e8b37c8a7363d33fbfc4/ty-0.0.35-py3-none-win_amd64.whl", hash = "sha256:6a0a6d259f6f2f8f2f954c6f013d4e0b5eba68af6b353bf19a47d59ec254a3d5", size = 11555691, upload-time = "2026-05-10T18:25:07.792Z" },
|
|
239
|
+
{ url = "https://files.pythonhosted.org/packages/7a/fb/59325221bce52f6e833d6865ce8360ef7d5e1e21151b38df6dc77c4327a7/ty-0.0.35-py3-none-win_arm64.whl", hash = "sha256:619c52c0fb2aa21961a848a1995135ad3b6d0a9aa54da0194e60f679cc200e13", size = 10925457, upload-time = "2026-05-10T18:25:10.352Z" },
|
|
240
|
+
]
|
|
241
|
+
|
|
242
|
+
[[package]]
|
|
243
|
+
name = "typeguard"
|
|
244
|
+
version = "4.5.1"
|
|
245
|
+
source = { registry = "https://pypi.org/simple" }
|
|
246
|
+
dependencies = [
|
|
247
|
+
{ name = "typing-extensions" },
|
|
248
|
+
]
|
|
249
|
+
sdist = { url = "https://files.pythonhosted.org/packages/2b/e8/66e25efcc18542d58706ce4e50415710593721aae26e794ab1dec34fb66f/typeguard-4.5.1.tar.gz", hash = "sha256:f6f8ecbbc819c9bc749983cc67c02391e16a9b43b8b27f15dc70ed7c4a007274", size = 80121, upload-time = "2026-02-19T16:09:03.392Z" }
|
|
250
|
+
wheels = [
|
|
251
|
+
{ url = "https://files.pythonhosted.org/packages/91/88/b55b3117287a8540b76dbdd87733808d4d01c8067a3b339408c250bb3600/typeguard-4.5.1-py3-none-any.whl", hash = "sha256:44d2bf329d49a244110a090b55f5f91aa82d9a9834ebfd30bcc73651e4a8cc40", size = 36745, upload-time = "2026-02-19T16:09:01.6Z" },
|
|
252
|
+
]
|
|
253
|
+
|
|
254
|
+
[[package]]
|
|
255
|
+
name = "typing-extensions"
|
|
256
|
+
version = "4.15.0"
|
|
257
|
+
source = { registry = "https://pypi.org/simple" }
|
|
258
|
+
sdist = { url = "https://files.pythonhosted.org/packages/72/94/1a15dd82efb362ac84269196e94cf00f187f7ed21c242792a923cdb1c61f/typing_extensions-4.15.0.tar.gz", hash = "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466", size = 109391, upload-time = "2025-08-25T13:49:26.313Z" }
|
|
259
|
+
wheels = [
|
|
260
|
+
{ url = "https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548", size = 44614, upload-time = "2025-08-25T13:49:24.86Z" },
|
|
261
|
+
]
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
__all__ = [
|
|
2
|
-
'value_or',
|
|
3
|
-
]
|
|
4
|
-
|
|
5
|
-
import sys
|
|
6
|
-
from collections.abc import Sequence
|
|
7
|
-
from pathlib import Path
|
|
8
|
-
from typing import Optional, TypeVar
|
|
9
|
-
|
|
10
|
-
import oslex
|
|
11
|
-
if sys.platform=='win32':
|
|
12
|
-
from ntstatus import NtStatus, NtStatusSeverity, ThirtyTwoBits
|
|
13
|
-
else:
|
|
14
|
-
import signal
|
|
15
|
-
|
|
16
|
-
T = TypeVar('T')
|
|
17
|
-
U = TypeVar('U')
|
|
18
|
-
|
|
19
|
-
def value_or(value: T | None, default: U) -> T | U:
|
|
20
|
-
if value is None:
|
|
21
|
-
return default
|
|
22
|
-
else:
|
|
23
|
-
return value
|
|
24
|
-
|
|
25
|
-
def oslex_join(cmd: Sequence[str | Path]) -> str:
|
|
26
|
-
return oslex.join([str(arg) for arg in cmd])
|
|
27
|
-
|
|
28
|
-
def stringify_exit_code(exit_code: int) -> Optional[str]:
|
|
29
|
-
if sys.platform=='win32':
|
|
30
|
-
# Windows
|
|
31
|
-
try:
|
|
32
|
-
bits = ThirtyTwoBits(exit_code)
|
|
33
|
-
except ValueError:
|
|
34
|
-
return None
|
|
35
|
-
|
|
36
|
-
try:
|
|
37
|
-
code = NtStatus(bits)
|
|
38
|
-
if code.severity!=NtStatusSeverity.STATUS_SEVERITY_SUCCESS:
|
|
39
|
-
return code.name
|
|
40
|
-
except ValueError:
|
|
41
|
-
pass
|
|
42
|
-
|
|
43
|
-
return f'0x{bits.unsigned_value:08X}'
|
|
44
|
-
else:
|
|
45
|
-
# POSIX
|
|
46
|
-
if exit_code<0:
|
|
47
|
-
try:
|
|
48
|
-
return signal.Signals(-exit_code).name
|
|
49
|
-
except ValueError:
|
|
50
|
-
return 'unknown signal'
|
|
51
|
-
|
|
52
|
-
return None
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import fancy_subprocess
|
|
2
|
-
from typing import Unpack
|
|
3
|
-
|
|
4
|
-
def grab_output(cmd: list[str], **kwargs: Unpack[fancy_subprocess.RunParams]) -> str:
|
|
5
|
-
# Raises ValueError if there are unknown parameters in kwargs or if a keyword argument's type is incorrect
|
|
6
|
-
fancy_subprocess.check_run_params(**kwargs)
|
|
7
|
-
|
|
8
|
-
# Make a copy of keyword arguments to be edited
|
|
9
|
-
forwarded_args = kwargs.copy()
|
|
10
|
-
# Make sure nothing's printed, raise ValueError if caller tries to specify "output_quiet" or "message_quiet"
|
|
11
|
-
fancy_subprocess.force_run_params(forwarded_args, message_quiet=True, output_quiet=True)
|
|
12
|
-
# Handle encoding/decoding errors by replacing them with placeholder character by default, but allow callers to still customize behaviour
|
|
13
|
-
fancy_subprocess.change_default_run_params(forwarded_args, errors='replace')
|
|
14
|
-
|
|
15
|
-
# Run command, raise fancy_subprocess.RunError on failure
|
|
16
|
-
result = fancy_subprocess.run(cmd, **forwarded_args)
|
|
17
|
-
|
|
18
|
-
# Return combined stdout and stderr
|
|
19
|
-
return result.output
|
|
20
|
-
|
|
21
|
-
comspec = grab_output(['cmd', '/c', 'echo', '%COMSPEC%'])
|
|
22
|
-
print(f'COMSPEC={comspec}')
|
|
23
|
-
|
|
24
|
-
files = grab_output(['cmd', '/c', 'dirr', '/b', '/o:n'], retry=2) # "dir" intentionally misspelled as "dirr"
|
|
25
|
-
print('Files in current directory:')
|
|
26
|
-
print(files)
|
fancy_subprocess-2.2/uv.lock
DELETED
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
version = 1
|
|
2
|
-
revision = 1
|
|
3
|
-
requires-python = ">=3.10"
|
|
4
|
-
|
|
5
|
-
[[package]]
|
|
6
|
-
name = "fancy-subprocess"
|
|
7
|
-
version = "2.2"
|
|
8
|
-
source = { editable = "." }
|
|
9
|
-
dependencies = [
|
|
10
|
-
{ name = "ntstatus" },
|
|
11
|
-
{ name = "oslex" },
|
|
12
|
-
{ name = "pathext" },
|
|
13
|
-
{ name = "typeguard" },
|
|
14
|
-
{ name = "typing-extensions" },
|
|
15
|
-
]
|
|
16
|
-
|
|
17
|
-
[package.metadata]
|
|
18
|
-
requires-dist = [
|
|
19
|
-
{ name = "ntstatus", specifier = ">=1.1,<2" },
|
|
20
|
-
{ name = "oslex", specifier = ">=0.1.3,<2" },
|
|
21
|
-
{ name = "pathext", specifier = ">=1.5,<2" },
|
|
22
|
-
{ name = "typeguard", specifier = ">=4.4.2,<5" },
|
|
23
|
-
{ name = "typing-extensions", specifier = ">=4.14,<5" },
|
|
24
|
-
]
|
|
25
|
-
|
|
26
|
-
[[package]]
|
|
27
|
-
name = "more-itertools"
|
|
28
|
-
version = "10.7.0"
|
|
29
|
-
source = { registry = "https://pypi.org/simple" }
|
|
30
|
-
sdist = { url = "https://files.pythonhosted.org/packages/ce/a0/834b0cebabbfc7e311f30b46c8188790a37f89fc8d756660346fe5abfd09/more_itertools-10.7.0.tar.gz", hash = "sha256:9fddd5403be01a94b204faadcff459ec3568cf110265d3c54323e1e866ad29d3", size = 127671 }
|
|
31
|
-
wheels = [
|
|
32
|
-
{ url = "https://files.pythonhosted.org/packages/2b/9f/7ba6f94fc1e9ac3d2b853fdff3035fb2fa5afbed898c4a72b8a020610594/more_itertools-10.7.0-py3-none-any.whl", hash = "sha256:d43980384673cb07d2f7d2d918c616b30c659c089ee23953f601d6609c67510e", size = 65278 },
|
|
33
|
-
]
|
|
34
|
-
|
|
35
|
-
[[package]]
|
|
36
|
-
name = "mslex"
|
|
37
|
-
version = "1.3.0"
|
|
38
|
-
source = { registry = "https://pypi.org/simple" }
|
|
39
|
-
sdist = { url = "https://files.pythonhosted.org/packages/e0/97/7022667073c99a0fe028f2e34b9bf76b49a611afd21b02527fbfd92d4cd5/mslex-1.3.0.tar.gz", hash = "sha256:641c887d1d3db610eee2af37a8e5abda3f70b3006cdfd2d0d29dc0d1ae28a85d", size = 11583 }
|
|
40
|
-
wheels = [
|
|
41
|
-
{ url = "https://files.pythonhosted.org/packages/64/f2/66bd65ca0139675a0d7b18f0bada6e12b51a984e41a76dbe44761bf1b3ee/mslex-1.3.0-py3-none-any.whl", hash = "sha256:c7074b347201b3466fc077c5692fbce9b5f62a63a51f537a53fbbd02eff2eea4", size = 7820 },
|
|
42
|
-
]
|
|
43
|
-
|
|
44
|
-
[[package]]
|
|
45
|
-
name = "ntstatus"
|
|
46
|
-
version = "1.1"
|
|
47
|
-
source = { registry = "https://pypi.org/simple" }
|
|
48
|
-
sdist = { url = "https://files.pythonhosted.org/packages/b5/99/41f6934b2dc1b02c6366b9b5d5211f3dc8eb08c9f9d8813e58fe4f09f9b4/ntstatus-1.1.tar.gz", hash = "sha256:542069b3d0d654a37b9e068caaf4d29c8e3f9c1a2a4991ed0ec8c7a858022ee2", size = 37824 }
|
|
49
|
-
wheels = [
|
|
50
|
-
{ url = "https://files.pythonhosted.org/packages/a5/cc/c9493a2a64dd9cfa8edf554028571f29398cb6fc693e6f4919f762994768/ntstatus-1.1-py3-none-any.whl", hash = "sha256:303239b3286fc0529fc8fd2daad6465ab7f5b2e0bc6abfdf785d48fbab1f2a54", size = 36674 },
|
|
51
|
-
]
|
|
52
|
-
|
|
53
|
-
[[package]]
|
|
54
|
-
name = "oslex"
|
|
55
|
-
version = "0.1.3"
|
|
56
|
-
source = { registry = "https://pypi.org/simple" }
|
|
57
|
-
dependencies = [
|
|
58
|
-
{ name = "mslex" },
|
|
59
|
-
]
|
|
60
|
-
sdist = { url = "https://files.pythonhosted.org/packages/5e/a9/ebd426ee0ca59fb5ba8f0039c53989f4ca475f2dd9583b5719e2fb01602c/oslex-0.1.3.tar.gz", hash = "sha256:1ed4cd82c75df2a8bcb0da34400984183753933155d0c7d999fa533137685f2d", size = 4415 }
|
|
61
|
-
wheels = [
|
|
62
|
-
{ url = "https://files.pythonhosted.org/packages/8a/21/f9d1c6196533d5e43625a71244796d6ec2565318f2d91f6c10ec461222f1/oslex-0.1.3-py3-none-any.whl", hash = "sha256:71acb8a1d42ed78ddd213a1d3a628bbf837f758bd2999c91df7ce57972466bdf", size = 3546 },
|
|
63
|
-
]
|
|
64
|
-
|
|
65
|
-
[[package]]
|
|
66
|
-
name = "pathext"
|
|
67
|
-
version = "1.5"
|
|
68
|
-
source = { registry = "https://pypi.org/simple" }
|
|
69
|
-
dependencies = [
|
|
70
|
-
{ name = "more-itertools" },
|
|
71
|
-
]
|
|
72
|
-
sdist = { url = "https://files.pythonhosted.org/packages/09/b3/cd7d7282c1640300630e963b84b6e202862206f5ac24959015d83372e16c/pathext-1.5.tar.gz", hash = "sha256:cbfd6f697a4874be7ea37109dbf60f108d451b44bb3df290f1560c75fa16bb87", size = 6424 }
|
|
73
|
-
wheels = [
|
|
74
|
-
{ url = "https://files.pythonhosted.org/packages/d0/d0/aab254e2ba1e2a390261ef746c4129ef81b2d13289850380c5273026915d/pathext-1.5-py3-none-any.whl", hash = "sha256:3aedc261736dc714881676847dcc20ce2246b09d331ec09276b478477a469530", size = 7325 },
|
|
75
|
-
]
|
|
76
|
-
|
|
77
|
-
[[package]]
|
|
78
|
-
name = "typeguard"
|
|
79
|
-
version = "4.4.3"
|
|
80
|
-
source = { registry = "https://pypi.org/simple" }
|
|
81
|
-
dependencies = [
|
|
82
|
-
{ name = "typing-extensions" },
|
|
83
|
-
]
|
|
84
|
-
sdist = { url = "https://files.pythonhosted.org/packages/34/53/f701077a29ddf65ed4556119961ef517d767c07f15f6cdf0717ad985426b/typeguard-4.4.3.tar.gz", hash = "sha256:be72b9c85f322c20459b29060c5c099cd733d5886c4ee14297795e62b0c0d59b", size = 75072 }
|
|
85
|
-
wheels = [
|
|
86
|
-
{ url = "https://files.pythonhosted.org/packages/5c/18/662e2a14fcdbbc9e7842ad801a7f9292fcd6cf7df43af94e59ac9c0da9af/typeguard-4.4.3-py3-none-any.whl", hash = "sha256:7d8b4a3d280257fd1aa29023f22de64e29334bda0b172ff1040f05682223795e", size = 34855 },
|
|
87
|
-
]
|
|
88
|
-
|
|
89
|
-
[[package]]
|
|
90
|
-
name = "typing-extensions"
|
|
91
|
-
version = "4.14.0"
|
|
92
|
-
source = { registry = "https://pypi.org/simple" }
|
|
93
|
-
sdist = { url = "https://files.pythonhosted.org/packages/d1/bc/51647cd02527e87d05cb083ccc402f93e441606ff1f01739a62c8ad09ba5/typing_extensions-4.14.0.tar.gz", hash = "sha256:8676b788e32f02ab42d9e7c61324048ae4c6d844a399eebace3d4979d75ceef4", size = 107423 }
|
|
94
|
-
wheels = [
|
|
95
|
-
{ url = "https://files.pythonhosted.org/packages/69/e0/552843e0d356fbb5256d21449fa957fa4eff3bbc135a74a691ee70c7c5da/typing_extensions-4.14.0-py3-none-any.whl", hash = "sha256:a1514509136dd0b477638fc68d6a91497af5076466ad0fa6c338e44e359944af", size = 43839 },
|
|
96
|
-
]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|