ask-shell 0.10.0__tar.gz → 0.10.2__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.
- {ask_shell-0.10.0 → ask_shell-0.10.2}/PKG-INFO +1 -1
- {ask_shell-0.10.0 → ask_shell-0.10.2}/ask_shell/__init__.py +1 -1
- {ask_shell-0.10.0 → ask_shell-0.10.2}/ask_shell/_internal/_run.py +3 -1
- {ask_shell-0.10.0 → ask_shell-0.10.2}/ask_shell/_internal/models.py +31 -11
- {ask_shell-0.10.0 → ask_shell-0.10.2}/pyproject.toml +1 -1
- {ask_shell-0.10.0 → ask_shell-0.10.2}/.gitignore +0 -0
- {ask_shell-0.10.0 → ask_shell-0.10.2}/LICENSE +0 -0
- {ask_shell-0.10.0 → ask_shell-0.10.2}/README.md +0 -0
- {ask_shell-0.10.0 → ask_shell-0.10.2}/ask_shell/__main__.py +0 -0
- {ask_shell-0.10.0 → ask_shell-0.10.2}/ask_shell/_internal/__init__.py +0 -0
- {ask_shell-0.10.0 → ask_shell-0.10.2}/ask_shell/_internal/_run_env.py +0 -0
- {ask_shell-0.10.0 → ask_shell-0.10.2}/ask_shell/_internal/events.py +0 -0
- {ask_shell-0.10.0 → ask_shell-0.10.2}/ask_shell/_internal/global_callbacks.py +0 -0
- {ask_shell-0.10.0 → ask_shell-0.10.2}/ask_shell/_internal/interactive.py +0 -0
- {ask_shell-0.10.0 → ask_shell-0.10.2}/ask_shell/_internal/live_print_context.py +0 -0
- {ask_shell-0.10.0 → ask_shell-0.10.2}/ask_shell/_internal/rich_live.py +0 -0
- {ask_shell-0.10.0 → ask_shell-0.10.2}/ask_shell/_internal/rich_live_callback.py +0 -0
- {ask_shell-0.10.0 → ask_shell-0.10.2}/ask_shell/_internal/rich_progress.py +0 -0
- {ask_shell-0.10.0 → ask_shell-0.10.2}/ask_shell/_internal/rich_run_state.py +0 -0
- {ask_shell-0.10.0 → ask_shell-0.10.2}/ask_shell/_internal/run_pool.py +0 -0
- {ask_shell-0.10.0 → ask_shell-0.10.2}/ask_shell/_internal/typer_command.py +0 -0
- {ask_shell-0.10.0 → ask_shell-0.10.2}/ask_shell/ask.py +0 -0
- {ask_shell-0.10.0 → ask_shell-0.10.2}/ask_shell/console.py +0 -0
- {ask_shell-0.10.0 → ask_shell-0.10.2}/ask_shell/py.typed +0 -0
- {ask_shell-0.10.0 → ask_shell-0.10.2}/ask_shell/settings.py +0 -0
- {ask_shell-0.10.0 → ask_shell-0.10.2}/ask_shell/shell.py +0 -0
- {ask_shell-0.10.0 → ask_shell-0.10.2}/ask_shell/shell_events.py +0 -0
- {ask_shell-0.10.0 → ask_shell-0.10.2}/ask_shell/test_docs.py +0 -0
- {ask_shell-0.10.0 → ask_shell-0.10.2}/examples/apply_live/__init__.py +0 -0
- {ask_shell-0.10.0 → ask_shell-0.10.2}/examples/apply_live/cli.py +0 -0
- {ask_shell-0.10.0 → ask_shell-0.10.2}/examples/apply_live/stream_handler.py +0 -0
- {ask_shell-0.10.0 → ask_shell-0.10.2}/scripts/fix_source_links.py +0 -0
|
@@ -415,10 +415,12 @@ def _execute_run(shell_run: ShellRun) -> ShellRun:
|
|
|
415
415
|
config = shell_run.config
|
|
416
416
|
queue = shell_run._queue
|
|
417
417
|
|
|
418
|
+
ctx = shell_run._callback_context
|
|
419
|
+
|
|
418
420
|
def queue_consumer():
|
|
419
421
|
for message in queue:
|
|
420
422
|
try:
|
|
421
|
-
shell_run._on_event
|
|
423
|
+
ctx.run(shell_run._on_event, message)
|
|
422
424
|
except BaseException as e:
|
|
423
425
|
logger.warning(f"Error processing message '{type(message).__name__}' for {shell_run}: {e!r}")
|
|
424
426
|
logger.exception(e)
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
+
import contextvars
|
|
3
4
|
import logging
|
|
4
5
|
import os
|
|
5
6
|
import platform
|
|
7
|
+
import re
|
|
6
8
|
import subprocess
|
|
7
9
|
import sys
|
|
8
10
|
from concurrent.futures import Future
|
|
@@ -124,6 +126,23 @@ def _resolve_binary(binary_name: str, cwd: Path) -> Path:
|
|
|
124
126
|
raise ValueError(f"Binary or non-executable '{binary_name}' not found. {install}")
|
|
125
127
|
|
|
126
128
|
|
|
129
|
+
class _ShellTokenSplit(NamedTuple):
|
|
130
|
+
first: str
|
|
131
|
+
remainder: str
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
_FIRST_SHELL_TOKEN = re.compile(r"(?P<first>\S+)(?P<remainder>.*)", re.DOTALL)
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
def _split_first_shell_token(shell_input: str) -> _ShellTokenSplit:
|
|
138
|
+
stripped = shell_input.lstrip()
|
|
139
|
+
if not stripped:
|
|
140
|
+
raise ValueError("shell_input must not be empty")
|
|
141
|
+
match = _FIRST_SHELL_TOKEN.match(stripped)
|
|
142
|
+
assert match is not None
|
|
143
|
+
return _ShellTokenSplit(match.group("first"), match.group("remainder"))
|
|
144
|
+
|
|
145
|
+
|
|
127
146
|
class ShellConfig(Entity):
|
|
128
147
|
"""
|
|
129
148
|
>>> ShellConfig("some_script").print_prefix
|
|
@@ -201,16 +220,14 @@ class ShellConfig(Entity):
|
|
|
201
220
|
|
|
202
221
|
@property
|
|
203
222
|
def binary_file_args(self) -> ShellInput:
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
return ShellInput(
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
case _:
|
|
213
|
-
raise ValueError("shell_input must not be empty")
|
|
223
|
+
split = _split_first_shell_token(self.shell_input)
|
|
224
|
+
args = split.remainder.strip().split()
|
|
225
|
+
if os.sep in split.first:
|
|
226
|
+
file_or_binary_path = Path(split.first).resolve()
|
|
227
|
+
if is_executable(file_or_binary_path):
|
|
228
|
+
return ShellInput("", file_or_binary_path, args)
|
|
229
|
+
return ShellInput(split.first, None, args)
|
|
230
|
+
return ShellInput(split.first, None, args)
|
|
214
231
|
|
|
215
232
|
def _infer_print_prefix(self, parsed_input: ShellInput):
|
|
216
233
|
cwd = self.cwd
|
|
@@ -240,8 +257,10 @@ class ShellConfig(Entity):
|
|
|
240
257
|
raise ValueError(f"cwd {self.cwd} does not exist")
|
|
241
258
|
parsed_input = self.binary_file_args
|
|
242
259
|
if not self.skip_binary_check and parsed_input.is_binary_call:
|
|
260
|
+
# ponytail: first-token only; full shlex if quoted binary paths matter
|
|
261
|
+
remainder = _split_first_shell_token(self.shell_input).remainder
|
|
243
262
|
binary_path = _resolve_binary(parsed_input.binary_name, self.cwd)
|
|
244
|
-
self.shell_input = f"{binary_path}
|
|
263
|
+
self.shell_input = f"{binary_path}{remainder}"
|
|
245
264
|
if self.is_binary_call is None:
|
|
246
265
|
self.is_binary_call = parsed_input.is_binary_call
|
|
247
266
|
if self.print_prefix is None:
|
|
@@ -293,6 +312,7 @@ class ShellRun:
|
|
|
293
312
|
_stderr_log_path: Path | None = field(init=False, default=None)
|
|
294
313
|
_queue: ShellRunQueueT = field(init=False, default_factory=ClosableQueue)
|
|
295
314
|
_lock: RLock = field(init=False, default_factory=RLock)
|
|
315
|
+
_callback_context: contextvars.Context = field(default_factory=contextvars.copy_context, init=False)
|
|
296
316
|
|
|
297
317
|
@property
|
|
298
318
|
def has_started(self) -> bool:
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|