Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .changelog/011.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
name: console
ts: 2026-03-23 21:41:45.646042+00:00
type: fix
author: Espen Albert
changelog_message: 'fix: also wrap logging for sub apps'
message: 'fix: also wrap logging for sub apps'
short_sha: a411a8
21 changes: 21 additions & 0 deletions ask_shell/_internal/rich_progress_test.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import logging

import pytest

from ask_shell._internal.rich_live import get_live, pause_live
from ask_shell._internal.rich_progress import (
get_default_progress_manager,
Expand Down Expand Up @@ -70,3 +72,22 @@ def test_task_should_update_progress_with_logging(capture_console):
assert "Test Task" in out
assert "20%" in out
assert "60%" in out


def test_task_context_system_exit_zero_logs_success(caplog):
caplog.set_level(logging.INFO)
with pytest.raises(SystemExit):
with new_task("se0", total=1):
raise SystemExit(0)
assert "✅" in caplog.text


def test_task_context_exception_with_exit_code_attr_zero_logs_success(caplog):
class QuietExit(Exception):
exit_code = 0

caplog.set_level(logging.INFO)
with pytest.raises(QuietExit):
with new_task("qe0", total=1):
raise QuietExit()
assert "✅" in caplog.text
57 changes: 45 additions & 12 deletions ask_shell/_internal/typer_command.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,42 @@ def wrapper(*args, **kwargs):
return decorator


def _wrap_typer_tree_commands(
app: typer.Typer,
*,
settings: AskShellSettings,
log_path_prefix: str,
skip_except_hook: bool,
use_app_name_command_for_logs: bool,
render_rich_error_on_sys_exit: bool,
) -> None:
for command in app.registered_commands:
command.callback = track_progress_decorator(
skip_except_hook=skip_except_hook,
settings=settings,
use_app_name_command_for_logs=use_app_name_command_for_logs,
app_name=log_path_prefix,
command_name=command.name or command.callback.__name__, # type: ignore
skip_rich_exception=not render_rich_error_on_sys_exit,
)(
command.callback # type: ignore
)
for group in app.registered_groups:
nested = group.typer_instance
if nested is None:
continue
segment = group.name or nested.info.name or "group"
child_prefix = f"{log_path_prefix}/{segment}"
_wrap_typer_tree_commands(
nested,
settings=settings,
log_path_prefix=child_prefix,
skip_except_hook=skip_except_hook,
use_app_name_command_for_logs=use_app_name_command_for_logs,
render_rich_error_on_sys_exit=render_rich_error_on_sys_exit,
)


def remove_secrets(message: str, secrets: list[str]) -> str:
for secret in secrets:
message = message.replace(secret, "***")
Expand Down Expand Up @@ -141,18 +177,15 @@ def configure_logging(
render_rich_error_on_sys_exit: bool = False,
) -> logging.Handler:
settings = settings or AskShellSettings.from_env()
app_name = app.info.name or "typer_app"
for command in app.registered_commands:
command.callback = track_progress_decorator(
skip_except_hook=skip_except_hook,
settings=settings,
use_app_name_command_for_logs=use_app_name_command_for_logs,
app_name=app_name,
command_name=command.name or command.callback.__name__, # type: ignore
skip_rich_exception=not render_rich_error_on_sys_exit,
)(
command.callback # type: ignore
)
root_prefix = app.info.name or "typer_app"
_wrap_typer_tree_commands(
app,
settings=settings,
log_path_prefix=root_prefix,
skip_except_hook=skip_except_hook,
use_app_name_command_for_logs=use_app_name_command_for_logs,
render_rich_error_on_sys_exit=render_rich_error_on_sys_exit,
)
handler = RichHandler(rich_tracebacks=False, level=settings.log_level, console=get_live_console())
logging.basicConfig(
level=settings.log_level,
Expand Down
62 changes: 35 additions & 27 deletions ask_shell/_internal/typer_command_test.py
Original file line number Diff line number Diff line change
@@ -1,27 +1,35 @@
import logging

from ask_shell._internal.typer_command import hide_secrets


def test_hide_secrets(caplog, tmp_path):
root_logger = logging.getLogger()
assert root_logger.handlers
handler = root_logger.handlers[0]
assert isinstance(handler, logging.StreamHandler)
secrets = {
"SECRET_KEY": "my_secret_value",
"ANOTHER_KEY": "another",
"token": "adsfadf",
"ok": "some-value",
"my-secret-path": str(tmp_path),
}
hide_secrets(handler, secrets)
expect_hidden = {value for key, value in secrets.items() if key not in {"ok", "my-secret-path"}}
expect_shown = {value for key, value in secrets.items() if key in {"ok", "my-secret-path"}}
all_vars_logged = ",".join(f"{key}={value}" for key, value in secrets.items())
root_logger.warning(f"Logging all variables: {all_vars_logged}")
output = caplog.text
found_hidden = {value for value in expect_hidden if value in output}
assert not found_hidden
found_shown: set[str] = {value for value in expect_shown if value in output}
assert found_shown == expect_shown, f"Expected to find {expect_shown}, but found {found_shown}"
import pytest
import typer

from ask_shell._internal import typer_command


def test_configure_logging_wraps_commands_in_nested_typers() -> None:
root = typer.Typer(name="root")
sub = typer.Typer(help="sub")

@sub.command("leaf")
def leaf() -> None:
return None

root.add_typer(sub, name="grp")
nested = root.registered_groups[0].typer_instance
assert nested is not None
before = nested.registered_commands[0].callback
typer_command.configure_logging(root, skip_except_hook=True)
after = nested.registered_commands[0].callback
assert after is not before


def test_configure_logging_skips_group_without_typer_instance(monkeypatch: pytest.MonkeyPatch) -> None:
root = typer.Typer(name="r")
sub = typer.Typer(help="s")

@sub.command("x")
def x() -> None:
return None

root.add_typer(sub, name="g")
group_info = root.registered_groups[0]
monkeypatch.setattr(group_info, "typer_instance", None)
typer_command.configure_logging(root, skip_except_hook=True)
2 changes: 1 addition & 1 deletion docs/console/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ def add_renderable(renderable: ConsoleRenderable | RichCast | str, *, order: int
<a id="configure_logging_def"></a>

### function: `configure_logging`
- [source](../../ask_shell/_internal/typer_command.py#L133)
- [source](../../ask_shell/_internal/typer_command.py#L169)
> **Since:** 0.3.0

```python
Expand Down
Loading