From 11aca13f325ceb235077b349c71e9d24ccde7a79 Mon Sep 17 00:00:00 2001 From: Espen Albert Date: Fri, 15 May 2026 14:09:17 +0100 Subject: [PATCH 1/4] feat(ask-shell): Add shell run summary policy and mute flag --- ask_shell/_internal/_run.py | 4 ++ ask_shell/_internal/models.py | 1 + ask_shell/_internal/rich_progress.py | 8 +++- ask_shell/_internal/rich_run_state.py | 6 +++ ask_shell/_internal/rich_run_state_test.py | 51 ++++++++++++++++++++-- ask_shell/conftest.py | 5 ++- ask_shell/settings.py | 11 +++++ 7 files changed, 81 insertions(+), 5 deletions(-) diff --git a/ask_shell/_internal/_run.py b/ask_shell/_internal/_run.py index c474c87..1280973 100644 --- a/ask_shell/_internal/_run.py +++ b/ask_shell/_internal/_run.py @@ -484,6 +484,7 @@ def run( start_timeout: float | None = None, terminal_width: int | None = None, skip_interactive_check: bool | None = None, + mute_shell_summary: bool | None = None, ) -> ShellRun: config = _as_config( config, @@ -510,6 +511,7 @@ def run( skip_os_env=skip_os_env, terminal_width=terminal_width, skip_interactive_check=skip_interactive_check, + mute_shell_summary=mute_shell_summary, ) assert not config.user_input, ( "run() does not support user_input (only 1 should be active at a time), use run_and_wait() instead" @@ -549,6 +551,7 @@ def run_and_wait( user_input: bool | None = None, terminal_width: int | None = None, skip_interactive_check: bool | None = None, + mute_shell_summary: bool | None = None, ) -> ShellRun: config = _as_config( script, @@ -576,6 +579,7 @@ def run_and_wait( terminal_width=terminal_width, skip_interactive_check=skip_interactive_check, skip_progress_output=skip_progress_output, + mute_shell_summary=mute_shell_summary, ) run = ShellRun(config) future = _pool.submit(_execute_run, run) diff --git a/ask_shell/_internal/models.py b/ask_shell/_internal/models.py index 1889a07..04d8410 100644 --- a/ask_shell/_internal/models.py +++ b/ask_shell/_internal/models.py @@ -172,6 +172,7 @@ class ShellConfig(Entity): default=False, description="Skip transitive std out/err output, useful for large outputs that are not needed in the logs when running parallel scripts", ) + mute_shell_summary: bool = Field(default=False, description="Skip shell summary logging useful when you want to ✅ or ❌ in the logs") terminal_width: int | None = 999 # advanced settings diff --git a/ask_shell/_internal/rich_progress.py b/ask_shell/_internal/rich_progress.py index 60f6c49..30b9508 100644 --- a/ask_shell/_internal/rich_progress.py +++ b/ask_shell/_internal/rich_progress.py @@ -47,10 +47,16 @@ def log_task_done( error: BaseException | None = None, description_override: str | None = None, extra_parts: list[str] | None = None, + soft_failure: bool = False, ): exit_comji = "❌" if force_error or error is not None else "✅" description = description_override or task.description - log_call = logger.info if exit_comji == "✅" else logger.error + if exit_comji == "✅": + log_call = logger.info + elif soft_failure: + log_call = logger.warning + else: + log_call = logger.error message_parts = [f"{exit_comji} {description}"] if rich_task := task._rich_task: if finish_time := rich_task.finished_time: diff --git a/ask_shell/_internal/rich_run_state.py b/ask_shell/_internal/rich_run_state.py index 68db02a..7e72658 100644 --- a/ask_shell/_internal/rich_run_state.py +++ b/ask_shell/_internal/rich_run_state.py @@ -21,6 +21,7 @@ ShellRunEventT, ) from ask_shell._internal.rich_progress import ProgressManager, log_task_done, new_task +from ask_shell.settings import ShellRunSummary def _deque_default() -> deque[str]: @@ -144,6 +145,10 @@ def remove_run(self, run: ShellRun, error: BaseException | None = None) -> None: task.update(stderr=run_info.stderr_str) task.__exit__(None, None, None) run = run_info.run + if run.config.mute_shell_summary: + return + if run.config.settings.shell_run_summary == ShellRunSummary.ERRORS_ONLY and run.clean_complete: + return log_task_done( task, force_error=not run.clean_complete, @@ -151,4 +156,5 @@ def remove_run(self, run: ShellRun, error: BaseException | None = None) -> None: extra_parts=[ "" if run.current_attempt == 1 else f"attempt {run.current_attempt}", ], + soft_failure=run.config.allow_non_zero_exit and not run.clean_complete, ) diff --git a/ask_shell/_internal/rich_run_state_test.py b/ask_shell/_internal/rich_run_state_test.py index c35ae6f..87f86e2 100644 --- a/ask_shell/_internal/rich_run_state_test.py +++ b/ask_shell/_internal/rich_run_state_test.py @@ -1,4 +1,6 @@ -import logging +from unittest.mock import Mock, patch + +import pytest from ask_shell._internal.events import ShellRunAfter, ShellRunStdOutput from ask_shell._internal.models import ( @@ -7,8 +9,7 @@ ) from ask_shell._internal.rich_live import get_live from ask_shell._internal.rich_run_state import _RunState - -logger = logging.getLogger(__name__) +from ask_shell.settings import ShellRunSummary def test_run_with_output_is_logged_to_console(settings, capture_console, caplog): @@ -79,3 +80,47 @@ def test_skip_progress_output(settings, capture_console): state.remove_run(run, error=Exception("Test error")) output = capture_console.end_capture() assert "..." in output # Output is skipped + + +@pytest.mark.parametrize( + ("summary", "exit_code", "expect_log"), + [ + (ShellRunSummary.ERRORS_ONLY, 0, False), + (ShellRunSummary.ERRORS_ONLY, 1, True), + (ShellRunSummary.ALL, 0, True), + ], +) +@patch("ask_shell._internal.rich_run_state.log_task_done") +def test_remove_run_respects_shell_run_summary(mock_log_done, settings, summary, exit_code, expect_log): + cfg = ShellConfig( + shell_input='echo "x"', + settings=settings.model_copy(update={"shell_run_summary": summary}), + ) + run = ShellRun(config=cfg) + proc = Mock(spec=["returncode"]) + proc.returncode = exit_code + run.p_open = proc + state = _RunState() + state.add_run(run) + state.remove_run(run, error=None) + if expect_log: + mock_log_done.assert_called_once() + else: + mock_log_done.assert_not_called() + + +@patch("ask_shell._internal.rich_run_state.log_task_done") +def test_remove_run_mute_shell_summary_skips_log(mock_log_done, settings): + cfg = ShellConfig( + shell_input='echo "x"', + settings=settings, + mute_shell_summary=True, + ) + run = ShellRun(config=cfg) + proc = Mock(spec=["returncode"]) + proc.returncode = 1 + run.p_open = proc + state = _RunState() + state.add_run(run) + state.remove_run(run, error=None) + mock_log_done.assert_not_called() diff --git a/ask_shell/conftest.py b/ask_shell/conftest.py index 271ee91..e9bc0ae 100644 --- a/ask_shell/conftest.py +++ b/ask_shell/conftest.py @@ -79,7 +79,7 @@ def capture_console() -> Console: # type: ignore def create_run_mocked_config(user_input: bool = False) -> ShellRun: - """avoid ShellConfig validation erro""" + mock_settings = AskShellSettings.for_testing(global_callback_strings=[], remove_os_secrets=False) return ShellRun( config=Mock( spec=ShellConfig, @@ -88,5 +88,8 @@ def create_run_mocked_config(user_input: bool = False) -> ShellRun: print_prefix="Mocked Run", shell_input="echo 'Mocked Run Output'", skip_progress_output=False, + mute_shell_summary=False, + allow_non_zero_exit=False, + settings=mock_settings, ) ) diff --git a/ask_shell/settings.py b/ask_shell/settings.py index 3a22076..935c172 100644 --- a/ask_shell/settings.py +++ b/ask_shell/settings.py @@ -1,6 +1,7 @@ import logging import os from datetime import datetime, timedelta +from enum import StrEnum from functools import cached_property, lru_cache from pathlib import Path from pydoc import locate @@ -90,6 +91,11 @@ def as_upper(v: str) -> str: ] +class ShellRunSummary(StrEnum): + ALL = "all" + ERRORS_ONLY = "errors_only" + + class AskShellSettings(StaticSettings): model_config = ConfigDict(populate_by_name=True) # type: ignore log_level: LogLevelIgnoredCase = "UNSET" @@ -136,6 +142,11 @@ class AskShellSettings(StaticSettings): description="Runs once If `run_logs_dir` is not set. Can be 'yesterday' or a date string like '2023-01-01'. Will clean all logs up until the specified date but not that date itself.", alias=f"{ENV_PREFIX}RUN_LOGS_CLEAN", ) + ENV_NAME_SHELL_RUN_SUMMARY: ClassVar[str] = f"{ENV_PREFIX}SHELL_RUN_SUMMARY" + shell_run_summary: ShellRunSummary = Field( + default=ShellRunSummary.ALL, + alias=ENV_NAME_SHELL_RUN_SUMMARY, + ) @model_validator(mode="after") def ensure_vars_set(self) -> Self: From 8290ea1af6d9845b4a17725072b78df5051cff88 Mon Sep 17 00:00:00 2001 From: Espen Albert Date: Fri, 15 May 2026 14:21:40 +0100 Subject: [PATCH 2/4] minor fixes --- ask_shell/_internal/models.py | 4 +++- ask_shell/_internal/rich_run_state_test.py | 26 ++++++++++++++++++++-- uv.lock | 2 +- 3 files changed, 28 insertions(+), 4 deletions(-) diff --git a/ask_shell/_internal/models.py b/ask_shell/_internal/models.py index 04d8410..a9d5be9 100644 --- a/ask_shell/_internal/models.py +++ b/ask_shell/_internal/models.py @@ -172,7 +172,9 @@ class ShellConfig(Entity): default=False, description="Skip transitive std out/err output, useful for large outputs that are not needed in the logs when running parallel scripts", ) - mute_shell_summary: bool = Field(default=False, description="Skip shell summary logging useful when you want to ✅ or ❌ in the logs") + mute_shell_summary: bool = Field( + default=False, description="Skip shell summary logging useful when you want to ✅ or ❌ in the logs" + ) terminal_width: int | None = 999 # advanced settings diff --git a/ask_shell/_internal/rich_run_state_test.py b/ask_shell/_internal/rich_run_state_test.py index 87f86e2..5429052 100644 --- a/ask_shell/_internal/rich_run_state_test.py +++ b/ask_shell/_internal/rich_run_state_test.py @@ -8,9 +8,12 @@ ShellRun, ) from ask_shell._internal.rich_live import get_live +from ask_shell._internal.rich_progress import log_task_done from ask_shell._internal.rich_run_state import _RunState from ask_shell.settings import ShellRunSummary +_module = _RunState.__module__ + def test_run_with_output_is_logged_to_console(settings, capture_console, caplog): config = ShellConfig( @@ -90,7 +93,7 @@ def test_skip_progress_output(settings, capture_console): (ShellRunSummary.ALL, 0, True), ], ) -@patch("ask_shell._internal.rich_run_state.log_task_done") +@patch(f"{_module}.{log_task_done.__name__}") def test_remove_run_respects_shell_run_summary(mock_log_done, settings, summary, exit_code, expect_log): cfg = ShellConfig( shell_input='echo "x"', @@ -109,7 +112,7 @@ def test_remove_run_respects_shell_run_summary(mock_log_done, settings, summary, mock_log_done.assert_not_called() -@patch("ask_shell._internal.rich_run_state.log_task_done") +@patch(f"{_module}.{log_task_done.__name__}") def test_remove_run_mute_shell_summary_skips_log(mock_log_done, settings): cfg = ShellConfig( shell_input='echo "x"', @@ -124,3 +127,22 @@ def test_remove_run_mute_shell_summary_skips_log(mock_log_done, settings): state.add_run(run) state.remove_run(run, error=None) mock_log_done.assert_not_called() + + +@patch(f"{_module}.{log_task_done.__name__}") +def test_remove_run_allow_non_zero_exit_uses_soft_failure(mock_log_done, settings): + cfg = ShellConfig( + shell_input='echo "x"', + settings=settings, + allow_non_zero_exit=True, + ) + run = ShellRun(config=cfg) + proc = Mock(spec=["returncode"]) + proc.returncode = 1 + run.p_open = proc + state = _RunState() + state.add_run(run) + state.remove_run(run, error=None) + mock_log_done.assert_called_once() + _, kwargs = mock_log_done.call_args + assert kwargs["soft_failure"] diff --git a/uv.lock b/uv.lock index 597c367..342b785 100644 --- a/uv.lock +++ b/uv.lock @@ -22,7 +22,7 @@ wheels = [ [[package]] name = "ask-shell" -version = "0.5.3" +version = "0.6.0" source = { editable = "." } dependencies = [ { name = "model-lib", extra = ["toml"] }, From 3d5a0c51dcc46cb7a271cda12ce4b0a3212d64fb Mon Sep 17 00:00:00 2001 From: Espen Albert Date: Fri, 15 May 2026 14:24:58 +0100 Subject: [PATCH 3/4] re-runs package ext --- .changelog/014.yaml | 42 ++++++++++++++++++++++++++++++++++ .groups.yaml | 1 + ask_shell/__init__.py | 2 ++ docs/_root/askshellsettings.md | 4 +++- docs/_root/index.md | 24 ++++++++++++++++++- docs/console/index.md | 2 +- docs/shell/index.md | 8 +++---- docs/shell/run.md | 3 ++- docs/shell/run_and_wait.md | 5 ++-- docs/shell/shellconfig.md | 2 ++ docs/shell/shellerror.md | 2 +- 11 files changed, 84 insertions(+), 11 deletions(-) create mode 100644 .changelog/014.yaml diff --git a/.changelog/014.yaml b/.changelog/014.yaml new file mode 100644 index 0000000..cb22d54 --- /dev/null +++ b/.changelog/014.yaml @@ -0,0 +1,42 @@ +name: ShellRunSummary +ts: 2026-05-15 13:24:34.831384+00:00 +type: make_public +details: created in settings.py +full_path: settings.ShellRunSummary +group: __ROOT__ +--- +name: AskShellSettings +ts: 2026-05-15 13:24:35.322058+00:00 +type: additional_change +auto_generated: true +change_kind: optional_field_added +details: 'added optional field ''shell_run_summary'' (default: )' +field_name: shell_run_summary +group: __ROOT__ +--- +name: ShellConfig +ts: 2026-05-15 13:24:35.322069+00:00 +type: additional_change +auto_generated: true +change_kind: optional_field_added +details: 'added optional field ''mute_shell_summary'' (default: False)' +field_name: mute_shell_summary +group: shell +--- +name: run +ts: 2026-05-15 13:24:35.322077+00:00 +type: additional_change +auto_generated: true +change_kind: optional_param_added +details: 'added optional param ''mute_shell_summary'' (default: None)' +field_name: mute_shell_summary +group: shell +--- +name: run_and_wait +ts: 2026-05-15 13:24:35.322079+00:00 +type: additional_change +auto_generated: true +change_kind: optional_param_added +details: 'added optional param ''mute_shell_summary'' (default: None)' +field_name: mute_shell_summary +group: shell diff --git a/.groups.yaml b/.groups.yaml index 3c5e5e9..ba4baaa 100644 --- a/.groups.yaml +++ b/.groups.yaml @@ -5,6 +5,7 @@ groups: - settings owned_refs: - settings.AskShellSettings + - settings.ShellRunSummary - name: ask owned_modules: - _internal.interactive diff --git a/ask_shell/__init__.py b/ask_shell/__init__.py index 526f127..8bb7922 100644 --- a/ask_shell/__init__.py +++ b/ask_shell/__init__.py @@ -5,6 +5,7 @@ from ask_shell import shell_events from ask_shell import ask from ask_shell.settings import AskShellSettings +from ask_shell.settings import ShellRunSummary VERSION = "0.6.0" __all__ = [ @@ -13,4 +14,5 @@ "shell_events", "ask", "AskShellSettings", + "ShellRunSummary", ] diff --git a/docs/_root/askshellsettings.md b/docs/_root/askshellsettings.md index 5d70722..c1291a9 100644 --- a/docs/_root/askshellsettings.md +++ b/docs/_root/askshellsettings.md @@ -2,7 +2,7 @@ ## class: AskShellSettings -- [source](../../ask_shell/settings.py#L93) +- [source](../../ask_shell/settings.py#L99) > **Since:** 0.3.0 ```python @@ -19,6 +19,7 @@ class AskShellSettings(StaticSettings): remove_os_secrets: bool = ... run_logs_dir: Path | None = None run_logs_clean: str = 'yesterday' + shell_run_summary: ShellRunSummary = ``` @@ -69,6 +70,7 @@ class AskShellSettings(StaticSettings): | Version | Change | |---------|--------| +| unreleased | added optional field 'shell_run_summary' (default: ) | | 0.6.0 | field 'thread_count' default: 50 -> 100 | | 0.3.2 | field 'run_logs_dir' default added: None | | 0.3.2 | field 'STATIC_DIR' default added: None | diff --git a/docs/_root/index.md b/docs/_root/index.md index c73af09..97bb64f 100644 --- a/docs/_root/index.md +++ b/docs/_root/index.md @@ -5,4 +5,26 @@ - [AskShellSettings](./askshellsettings.md) - \ No newline at end of file +- [`ShellRunSummary`](#shellrunsummary_def) + + +## Symbol Details + + + + +### class: `ShellRunSummary` +- [source](../../ask_shell/settings.py#L94) +> **Since:** unreleased + +```python +class ShellRunSummary(StrEnum): + ... +``` + +### Changes + +| Version | Change | +|---------|--------| +| unreleased | Made public | + \ No newline at end of file diff --git a/docs/console/index.md b/docs/console/index.md index 193c83d..e013767 100644 --- a/docs/console/index.md +++ b/docs/console/index.md @@ -130,7 +130,7 @@ def log_to_live(*objects, sep: str = ' ', end: str = '\n', style: str | Style | ### class: `new_task` -- [source](../../ask_shell/_internal/rich_progress.py#L162) +- [source](../../ask_shell/_internal/rich_progress.py#L168) > **Since:** 0.3.0 ```python diff --git a/docs/shell/index.md b/docs/shell/index.md index 4575f98..2ae3e37 100644 --- a/docs/shell/index.md +++ b/docs/shell/index.md @@ -27,7 +27,7 @@ ### class: `ShellRun` -- [source](../../ask_shell/_internal/models.py#L272) +- [source](../../ask_shell/_internal/models.py#L273) > **Since:** 0.3.0 ```python @@ -120,7 +120,7 @@ def kill_all_runs(immediate: bool = False, reason: str = '', abort_timeout: floa ### function: `run_error` -- [source](../../ask_shell/_internal/_run.py#L589) +- [source](../../ask_shell/_internal/_run.py#L593) > **Since:** 0.3.0 ```python @@ -156,7 +156,7 @@ def stop_runs_and_pool(reason: str = 'atexit', immediate: bool = False): ### function: `wait_on_ok_errors` -- [source](../../ask_shell/_internal/_run.py#L596) +- [source](../../ask_shell/_internal/_run.py#L600) > **Since:** 0.3.0 ```python @@ -174,7 +174,7 @@ def wait_on_ok_errors(*runs, timeout: float | None = None, skip_kill_timeouts: b ### exception: `AbortRetryError` -- [source](../../ask_shell/_internal/models.py#L523) +- [source](../../ask_shell/_internal/models.py#L524) - [Example: Stop retrying with a custom error by raising AbortRetryError from should_retry](../examples/shell/AbortRetryError.md) > **Since:** 0.5.0 diff --git a/docs/shell/run.md b/docs/shell/run.md index 787b2b9..e873676 100644 --- a/docs/shell/run.md +++ b/docs/shell/run.md @@ -6,7 +6,7 @@ > **Since:** 0.3.0 ```python -def run(config: ShellConfig | str, *, allow_non_zero_exit: bool | None = None, ansi_content: bool | None = None, attempts: int | None = None, cwd: str | Path | None = None, env: dict[str, str] | None = None, extra_popen_kwargs: dict | None = None, is_binary_call: bool | None = None, message_callbacks: list[Callable[[ShellRunBefore | ShellRunPOpenStarted | ShellRunStdStarted | ShellRunStdReadError | ShellRunStdOutput | ShellRunRetryAttempt | ShellRunAfter], bool]] | None = None, print_prefix: str | None = None, retry_initial_wait: float | None = None, retry_jitter: float | None = None, retry_max_wait: float | None = None, run_log_stem_prefix: str | None = None, run_output_dir: Path | None = None, settings: AskShellSettings | None = None, should_retry: Callable[[ShellRun], bool] | None = None, skip_binary_check: bool | None = None, skip_html_log_files: bool | None = None, skip_progress_output: bool | None = None, include_log_time: bool | None = None, skip_os_env: bool | None = None, start_timeout: float | None = None, terminal_width: int | None = None, skip_interactive_check: bool | None = None) -> ShellRun: +def run(config: ShellConfig | str, *, allow_non_zero_exit: bool | None = None, ansi_content: bool | None = None, attempts: int | None = None, cwd: str | Path | None = None, env: dict[str, str] | None = None, extra_popen_kwargs: dict | None = None, is_binary_call: bool | None = None, message_callbacks: list[Callable[[ShellRunBefore | ShellRunPOpenStarted | ShellRunStdStarted | ShellRunStdReadError | ShellRunStdOutput | ShellRunRetryAttempt | ShellRunAfter], bool]] | None = None, print_prefix: str | None = None, retry_initial_wait: float | None = None, retry_jitter: float | None = None, retry_max_wait: float | None = None, run_log_stem_prefix: str | None = None, run_output_dir: Path | None = None, settings: AskShellSettings | None = None, should_retry: Callable[[ShellRun], bool] | None = None, skip_binary_check: bool | None = None, skip_html_log_files: bool | None = None, skip_progress_output: bool | None = None, include_log_time: bool | None = None, skip_os_env: bool | None = None, start_timeout: float | None = None, terminal_width: int | None = None, skip_interactive_check: bool | None = None, mute_shell_summary: bool | None = None) -> ShellRun: ... ``` @@ -16,6 +16,7 @@ def run(config: ShellConfig | str, *, allow_non_zero_exit: bool | None = None, a | Version | Change | |---------|--------| +| unreleased | added optional param 'mute_shell_summary' (default: None) | | 0.5.1 | added optional param 'retry_max_wait' (default: None) | | 0.5.1 | added optional param 'retry_jitter' (default: None) | | 0.5.1 | added optional param 'retry_initial_wait' (default: None) | diff --git a/docs/shell/run_and_wait.md b/docs/shell/run_and_wait.md index d3d9716..e13921e 100644 --- a/docs/shell/run_and_wait.md +++ b/docs/shell/run_and_wait.md @@ -2,11 +2,11 @@ ## function: run_and_wait -- [source](../../ask_shell/_internal/_run.py#L524) +- [source](../../ask_shell/_internal/_run.py#L526) > **Since:** 0.3.0 ```python -def run_and_wait(script: ShellConfig | str, timeout: float | None = None, *, allow_non_zero_exit: bool | None = None, ansi_content: bool | None = None, attempts: int | None = None, cwd: str | Path | None = None, env: dict[str, str] | None = None, extra_popen_kwargs: dict | None = None, is_binary_call: bool | None = None, message_callbacks: list[Callable[[ShellRunBefore | ShellRunPOpenStarted | ShellRunStdStarted | ShellRunStdReadError | ShellRunStdOutput | ShellRunRetryAttempt | ShellRunAfter], bool]] | None = None, print_prefix: str | None = None, retry_initial_wait: float | None = None, retry_jitter: float | None = None, retry_max_wait: float | None = None, run_log_stem_prefix: str | None = None, run_output_dir: Path | None = None, settings: AskShellSettings | None = None, should_retry: Callable[[ShellRun], bool] | None = None, skip_binary_check: bool | None = None, skip_progress_output: bool | None = None, skip_html_log_files: bool | None = None, include_log_time: bool | None = None, skip_os_env: bool | None = None, user_input: bool | None = None, terminal_width: int | None = None, skip_interactive_check: bool | None = None) -> ShellRun: +def run_and_wait(script: ShellConfig | str, timeout: float | None = None, *, allow_non_zero_exit: bool | None = None, ansi_content: bool | None = None, attempts: int | None = None, cwd: str | Path | None = None, env: dict[str, str] | None = None, extra_popen_kwargs: dict | None = None, is_binary_call: bool | None = None, message_callbacks: list[Callable[[ShellRunBefore | ShellRunPOpenStarted | ShellRunStdStarted | ShellRunStdReadError | ShellRunStdOutput | ShellRunRetryAttempt | ShellRunAfter], bool]] | None = None, print_prefix: str | None = None, retry_initial_wait: float | None = None, retry_jitter: float | None = None, retry_max_wait: float | None = None, run_log_stem_prefix: str | None = None, run_output_dir: Path | None = None, settings: AskShellSettings | None = None, should_retry: Callable[[ShellRun], bool] | None = None, skip_binary_check: bool | None = None, skip_progress_output: bool | None = None, skip_html_log_files: bool | None = None, include_log_time: bool | None = None, skip_os_env: bool | None = None, user_input: bool | None = None, terminal_width: int | None = None, skip_interactive_check: bool | None = None, mute_shell_summary: bool | None = None) -> ShellRun: ... ``` @@ -16,6 +16,7 @@ def run_and_wait(script: ShellConfig | str, timeout: float | None = None, *, all | Version | Change | |---------|--------| +| unreleased | added optional param 'mute_shell_summary' (default: None) | | 0.5.1 | added optional param 'retry_max_wait' (default: None) | | 0.5.1 | added optional param 'retry_jitter' (default: None) | | 0.5.1 | added optional param 'retry_initial_wait' (default: None) | diff --git a/docs/shell/shellconfig.md b/docs/shell/shellconfig.md index 018df07..5d8ac29 100644 --- a/docs/shell/shellconfig.md +++ b/docs/shell/shellconfig.md @@ -28,6 +28,7 @@ class ShellConfig(Entity): run_log_stem_prefix: str = '' skip_html_log_files: bool = False skip_progress_output: bool = False + mute_shell_summary: bool = False terminal_width: int | None = 999 is_binary_call: bool = None settings: AskShellSettings = ... @@ -78,6 +79,7 @@ class ShellConfig(Entity): | Version | Change | |---------|--------| +| unreleased | added optional field 'mute_shell_summary' (default: False) | | 0.5.1 | added optional field 'retry_max_wait' (default: 60) | | 0.5.1 | added optional field 'retry_jitter' (default: 5) | | 0.5.1 | added optional field 'retry_initial_wait' (default: 5) | diff --git a/docs/shell/shellerror.md b/docs/shell/shellerror.md index c90a4c5..75a41a2 100644 --- a/docs/shell/shellerror.md +++ b/docs/shell/shellerror.md @@ -2,7 +2,7 @@ ## exception: ShellError -- [source](../../ask_shell/_internal/models.py#L487) +- [source](../../ask_shell/_internal/models.py#L488) > **Since:** 0.3.0 ```python From 22f984d21595c14a3345f9930526f982b1f344c0 Mon Sep 17 00:00:00 2001 From: Espen Albert Date: Fri, 15 May 2026 14:29:26 +0100 Subject: [PATCH 4/4] minor fixes --- docs/shell/index.md | 4 ++-- docs/shell/shellerror.md | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/shell/index.md b/docs/shell/index.md index 2ae3e37..c2ff26f 100644 --- a/docs/shell/index.md +++ b/docs/shell/index.md @@ -27,7 +27,7 @@ ### class: `ShellRun` -- [source](../../ask_shell/_internal/models.py#L273) +- [source](../../ask_shell/_internal/models.py#L275) > **Since:** 0.3.0 ```python @@ -174,7 +174,7 @@ def wait_on_ok_errors(*runs, timeout: float | None = None, skip_kill_timeouts: b ### exception: `AbortRetryError` -- [source](../../ask_shell/_internal/models.py#L524) +- [source](../../ask_shell/_internal/models.py#L526) - [Example: Stop retrying with a custom error by raising AbortRetryError from should_retry](../examples/shell/AbortRetryError.md) > **Since:** 0.5.0 diff --git a/docs/shell/shellerror.md b/docs/shell/shellerror.md index 75a41a2..2572813 100644 --- a/docs/shell/shellerror.md +++ b/docs/shell/shellerror.md @@ -2,7 +2,7 @@ ## exception: ShellError -- [source](../../ask_shell/_internal/models.py#L488) +- [source](../../ask_shell/_internal/models.py#L490) > **Since:** 0.3.0 ```python