ask-shell 0.9.0__tar.gz → 0.9.1__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.
Files changed (31) hide show
  1. {ask_shell-0.9.0 → ask_shell-0.9.1}/PKG-INFO +1 -1
  2. {ask_shell-0.9.0 → ask_shell-0.9.1}/ask_shell/__init__.py +1 -1
  3. {ask_shell-0.9.0 → ask_shell-0.9.1}/ask_shell/_internal/_run.py +24 -33
  4. {ask_shell-0.9.0 → ask_shell-0.9.1}/ask_shell/_internal/models.py +7 -7
  5. {ask_shell-0.9.0 → ask_shell-0.9.1}/pyproject.toml +1 -1
  6. {ask_shell-0.9.0 → ask_shell-0.9.1}/.gitignore +0 -0
  7. {ask_shell-0.9.0 → ask_shell-0.9.1}/LICENSE +0 -0
  8. {ask_shell-0.9.0 → ask_shell-0.9.1}/README.md +0 -0
  9. {ask_shell-0.9.0 → ask_shell-0.9.1}/ask_shell/__main__.py +0 -0
  10. {ask_shell-0.9.0 → ask_shell-0.9.1}/ask_shell/_internal/__init__.py +0 -0
  11. {ask_shell-0.9.0 → ask_shell-0.9.1}/ask_shell/_internal/_run_env.py +0 -0
  12. {ask_shell-0.9.0 → ask_shell-0.9.1}/ask_shell/_internal/events.py +0 -0
  13. {ask_shell-0.9.0 → ask_shell-0.9.1}/ask_shell/_internal/global_callbacks.py +0 -0
  14. {ask_shell-0.9.0 → ask_shell-0.9.1}/ask_shell/_internal/interactive.py +0 -0
  15. {ask_shell-0.9.0 → ask_shell-0.9.1}/ask_shell/_internal/rich_live.py +0 -0
  16. {ask_shell-0.9.0 → ask_shell-0.9.1}/ask_shell/_internal/rich_live_callback.py +0 -0
  17. {ask_shell-0.9.0 → ask_shell-0.9.1}/ask_shell/_internal/rich_progress.py +0 -0
  18. {ask_shell-0.9.0 → ask_shell-0.9.1}/ask_shell/_internal/rich_run_state.py +0 -0
  19. {ask_shell-0.9.0 → ask_shell-0.9.1}/ask_shell/_internal/run_pool.py +0 -0
  20. {ask_shell-0.9.0 → ask_shell-0.9.1}/ask_shell/_internal/typer_command.py +0 -0
  21. {ask_shell-0.9.0 → ask_shell-0.9.1}/ask_shell/ask.py +0 -0
  22. {ask_shell-0.9.0 → ask_shell-0.9.1}/ask_shell/console.py +0 -0
  23. {ask_shell-0.9.0 → ask_shell-0.9.1}/ask_shell/py.typed +0 -0
  24. {ask_shell-0.9.0 → ask_shell-0.9.1}/ask_shell/settings.py +0 -0
  25. {ask_shell-0.9.0 → ask_shell-0.9.1}/ask_shell/shell.py +0 -0
  26. {ask_shell-0.9.0 → ask_shell-0.9.1}/ask_shell/shell_events.py +0 -0
  27. {ask_shell-0.9.0 → ask_shell-0.9.1}/ask_shell/test_docs.py +0 -0
  28. {ask_shell-0.9.0 → ask_shell-0.9.1}/examples/apply_live/__init__.py +0 -0
  29. {ask_shell-0.9.0 → ask_shell-0.9.1}/examples/apply_live/cli.py +0 -0
  30. {ask_shell-0.9.0 → ask_shell-0.9.1}/examples/apply_live/stream_handler.py +0 -0
  31. {ask_shell-0.9.0 → ask_shell-0.9.1}/scripts/fix_source_links.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ask-shell
3
- Version: 0.9.0
3
+ Version: 0.9.1
4
4
  Summary: CLIs with prompts, shell runs, and testable flows
5
5
  Author-email: EspenAlbert <espen.albert1@gmail.com>
6
6
  License-Expression: MIT
@@ -7,7 +7,7 @@ from ask_shell import ask
7
7
  from ask_shell.settings import AskShellSettings
8
8
  from ask_shell.settings import ShellRunSummary
9
9
 
10
- VERSION = "0.9.0"
10
+ VERSION = "0.9.1"
11
11
  __all__ = [
12
12
  "shell",
13
13
  "console",
@@ -11,6 +11,7 @@
11
11
  from __future__ import annotations
12
12
 
13
13
  import atexit
14
+ import io
14
15
  import logging
15
16
  import os
16
17
  import random
@@ -27,7 +28,6 @@ from typing import IO, Any, Callable
27
28
  from model_lib import fields
28
29
  from rich.ansi import AnsiDecoder
29
30
  from rich.console import Console
30
- from rich.errors import MarkupError
31
31
  from zero_3rdparty.error import as_str_traceback
32
32
  from zero_3rdparty.future import add_done_callback, add_error_logging, chain_future
33
33
 
@@ -223,6 +223,12 @@ def _stream_one_character_at_a_time(stream: IO[str], on_line: Callable[[str], No
223
223
  on_line(buffer)
224
224
 
225
225
 
226
+ def _log_line(line: str, *, ansi_content: bool, decoder: AnsiDecoder) -> str:
227
+ if not ansi_content:
228
+ return line
229
+ return decoder.decode_line(line).plain
230
+
231
+
226
232
  def _read_until_complete(
227
233
  stream: IO[str],
228
234
  output_path: Path,
@@ -231,54 +237,39 @@ def _read_until_complete(
231
237
  config: ShellConfig,
232
238
  is_stdout: bool,
233
239
  ):
234
- with output_path.open("w") as f:
235
- console = Console(
236
- file=f,
237
- record=True,
238
- log_path=False,
239
- soft_wrap=True,
240
- log_time=config.include_log_time,
241
- width=config.terminal_width,
242
- markup=config.ansi_content,
243
- )
244
- on_console_ready(console)
245
- old_write = f.write
246
-
247
- def write_hook(text: str):
248
- # choosing to line.strip() as the writing to console will add padding depending on console width
249
- text_no_extras = [line.strip() for line in text.splitlines()]
250
- return old_write("\n".join(text_no_extras))
240
+ record_console = Console(
241
+ file=io.StringIO(),
242
+ record=True,
243
+ log_path=False,
244
+ log_time=config.include_log_time,
245
+ width=config.terminal_width,
246
+ markup=config.ansi_content,
247
+ )
248
+ on_console_ready(record_console)
249
+ ansi_decoder = AnsiDecoder()
251
250
 
252
- decoder = AnsiDecoder()
251
+ with output_path.open("w") as log_file:
253
252
 
254
- def write_hook_ansi(text: str):
255
- try:
256
- plain_text = "\n".join(decoder.decode_line(line).plain.strip() for line in text.splitlines())
257
- except MarkupError:
258
- return old_write(text)
259
- return old_write(plain_text)
253
+ def emit_line(line: str):
254
+ log_file.write(_log_line(line, ansi_content=config.ansi_content, decoder=ansi_decoder))
255
+ record_console.print(line, end="", overflow="ignore", crop=False, soft_wrap=False)
256
+ on_line(line)
260
257
 
261
- f.write = write_hook_ansi if config.ansi_content else write_hook
262
258
  if config.user_input:
263
259
  out_stream = sys.stdout if is_stdout else sys.stderr
264
260
 
265
- def _on_line(line: str):
266
- console.log(line, end="")
267
- on_line(line)
268
-
269
261
  def _on_char(char: str):
270
262
  out_stream.write(char)
271
263
  out_stream.flush()
272
264
 
273
265
  _stream_one_character_at_a_time(
274
266
  stream,
275
- on_line=_on_line,
267
+ on_line=emit_line,
276
268
  on_char=_on_char,
277
269
  )
278
270
  else:
279
271
  for line in iter(stream.readline, ""):
280
- console.log(line, end="")
281
- on_line(line)
272
+ emit_line(line)
282
273
 
283
274
 
284
275
  def _run(
@@ -443,14 +443,14 @@ class ShellRun:
443
443
  stream: Literal["stdout", "stderr"] = "stdout",
444
444
  ) -> OutputT:
445
445
  """Raises EmptyOutputError if the output is empty."""
446
- stream_content = self.stdout_one_line if stream == "stdout" else self.stderr_one_line
447
- if not stream_content:
446
+ content = self.stdout if stream == "stdout" else self.stderr
447
+ if not content:
448
448
  raise EmptyOutputError(self, stream=stream)
449
- elif output_t is list:
450
- return parse.parse_list(stream_content, output_format) # type: ignore
451
- elif output_t is dict:
452
- return parse.parse_dict(stream_content, output_format) # type: ignore
453
- return parse.parse_model(stream_content, t=output_t, format=output_format)
449
+ if output_t is list:
450
+ return parse.parse_list(content, output_format) # type: ignore
451
+ if output_t is dict:
452
+ return parse.parse_dict(content, output_format) # type: ignore
453
+ return parse.parse_model(content, t=output_t, format=output_format)
454
454
 
455
455
  @property
456
456
  def stderr(self) -> str:
@@ -2,7 +2,7 @@
2
2
 
3
3
  [project]
4
4
  name = "ask-shell"
5
- version = "0.9.0"
5
+ version = "0.9.1"
6
6
  description = "CLIs with prompts, shell runs, and testable flows"
7
7
  requires-python = ">=3.13"
8
8
  license = "MIT"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes