From ad1b646e78e8aac6c15e713f3f1513e404c05936 Mon Sep 17 00:00:00 2001 From: Ed Nutting Date: Thu, 15 Jan 2026 14:30:18 +0000 Subject: [PATCH] Always forward Gator warnings/errors to user regardless of --all-msg flag When --all-msg is NOT specified, Gator's own warnings and errors (like the command substitution warning) were not being surfaced to the user. This change ensures that WARNING, ERROR, and CRITICAL messages originating from Gator itself are always forwarded to the parent layer, while still respecting the --all-msg flag for filtering verbose output from invoked tools. Key changes: - Modified Logger.log() to forward high-severity messages (WARNING+) from Gator itself regardless of the forward setting - Messages forwarded from child processes are still filtered by --all-msg - Added test_linked_no_forward to verify the new behavior Co-Authored-By: Claude Sonnet 4.5 --- gator/common/logger.py | 5 ++- tests/common/test_logger.py | 71 +++++++++++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+), 1 deletion(-) diff --git a/gator/common/logger.py b/gator/common/logger.py index 3464a13..57cdb6d 100644 --- a/gator/common/logger.py +++ b/gator/common/logger.py @@ -152,8 +152,11 @@ async def log( # Generate a timestamp if required if timestamp is None: timestamp = datetime.now() + # Always forward warnings, errors, and critical messages from Gator itself + # (not forwarded from children), regardless of forward setting + should_forward = forward or (not forwarded and severity >= LogSeverity.WARNING) # If linked to parent and forwarding requested, push log upwards - if forward and self.ws_cli.linked and severity >= self.verbosity: + if should_forward and self.ws_cli.linked and severity >= self.verbosity: await self.ws_cli.log( timestamp=int(timestamp.timestamp()), hierarchy=hierarchy, diff --git a/tests/common/test_logger.py b/tests/common/test_logger.py index f2975b3..787c081 100644 --- a/tests/common/test_logger.py +++ b/tests/common/test_logger.py @@ -111,6 +111,77 @@ async def test_local(self, logger_local): ) logger._Logger__console.log.reset_mock() + @pytest.mark.asyncio + async def test_linked_no_forward(self, logger_linked): + """When forward=False, warnings and errors are still forwarded""" + logger = logger_linked + logger.forward = False + logger.verbosity = LogSeverity.DEBUG + # Debug should not be forwarded + await logger.debug("Testing debug") + assert not logger.ws_cli.log.called + logger._Logger__console.log.assert_called_with( + "[bold cyan]DEBUG [/bold cyan] " + TestLogger.ROOT_STR + " Testing debug" + ) + logger._Logger__console.log.reset_mock() + # Info should not be forwarded + await logger.info("Testing info") + assert not logger.ws_cli.log.called + logger._Logger__console.log.assert_called_with( + "[bold]INFO [/bold] " + TestLogger.ROOT_STR + " Testing info" + ) + logger._Logger__console.log.reset_mock() + # Warning should be forwarded (even though forward=False) + await logger.warning("Testing warning") + logger.ws_cli.log.assert_called_with( + timestamp=1234, + hierarchy="root", + severity="WARNING", + message="Testing warning", + posted=True, + ) + logger._Logger__console.log.assert_called_with( + "[bold yellow]WARNING[/bold yellow] " + TestLogger.ROOT_STR + " Testing warning" + ) + logger.ws_cli.log.reset_mock() + logger._Logger__console.log.reset_mock() + # Error should be forwarded (even though forward=False) + await logger.error("Testing error") + logger.ws_cli.log.assert_called_with( + timestamp=1234, + hierarchy="root", + severity="ERROR", + message="Testing error", + posted=True, + ) + logger._Logger__console.log.assert_called_with( + "[bold red]ERROR [/bold red] " + TestLogger.ROOT_STR + " Testing error" + ) + logger.ws_cli.log.reset_mock() + logger._Logger__console.log.reset_mock() + # Critical should be forwarded (even though forward=False) + await logger.critical("Testing critical") + logger.ws_cli.log.assert_called_with( + timestamp=1234, + hierarchy="root", + severity="CRITICAL", + message="Testing critical", + posted=True, + ) + logger._Logger__console.log.assert_called_with( + "[bold white on red]CRITICAL[/bold white on red] " + + TestLogger.ROOT_STR + + " Testing critical" + ) + logger.ws_cli.log.reset_mock() + logger._Logger__console.log.reset_mock() + # Forwarded messages should only be forwarded when forward=True + await logger.warning("Forwarded warning", forwarded=True) + assert not logger.ws_cli.log.called + logger._Logger__console.log.assert_called_with( + "[bold yellow]WARNING[/bold yellow] " + TestLogger.ROOT_STR + " Forwarded warning" + ) + @pytest.mark.asyncio async def test_linked(self, logger_linked): """Local logging goes to the console"""