From 7bd8be3e0700970f79ddb5537f35dfbd31caed17 Mon Sep 17 00:00:00 2001 From: Adriano Machado <60320+ammachado@users.noreply.github.com> Date: Sun, 6 Sep 2026 15:59:43 -0400 Subject: [PATCH] Clean up error output: color reset sequence and stat failure message Two unrelated-to-each-other-but-both-cosmetic fixes to how errors reach the user, split out of #469 where they did not belong. did/utils.py: the reset sequence emitted by color() was "\033[1;m", two SGR parameters where the second is empty. Per ECMA-48 an empty parameter defaults to 0, so a conforming terminal does end up reset, and this is not a bug on one. But it relies on that defaulting rule, which parsers that are not full terminals (log scrapers, CI log viewers, less without -R, some ANSI-stripping libraries) handle inconsistently, and it briefly enables bold on the way to resetting. "\033[0m" is the canonical reset and does not read as a typo. The three test_utils.py assertions follow from the change. did/stats.py: the failure path logged "Skipping %s due to %s" with a concurrent.futures.Future as the first argument, so it rendered a repr: Skipping due to Unable to fetch token The address and state tell the user nothing, and the one useful piece of information (which stat failed) is not there at all, since Future has no back-reference to the submitted callable. Dropping the useless half leaves the error text. Naming the stat properly would need a future -> stat mapping, which is a larger change than this. Co-Authored-By: Claude Opus 5 --- did/stats.py | 2 +- did/utils.py | 2 +- tests/unit/test_utils.py | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/did/stats.py b/did/stats.py index d1aca7cf7..6ff9fca6e 100644 --- a/did/stats.py +++ b/did/stats.py @@ -179,7 +179,7 @@ def check(self) -> None: try: f.result() except did.base.ReportError as error: - log.error("Skipping %s due to %s", f, error) + log.error("%s", error) sys.stdout.flush() sys.stderr.flush() diff --git a/did/utils.py b/did/utils.py index 9aca2fc36..bfb13aa51 100644 --- a/did/utils.py +++ b/did/utils.py @@ -521,7 +521,7 @@ def color( light_code = (1 if light else 0) # Starting and finishing sequence start = f"\033[{light_code}{text_color_code}{background_code}m" - finish = "\033[1;m" + finish = "\033[0m" return "".join([start, text, finish]) diff --git a/tests/unit/test_utils.py b/tests/unit/test_utils.py index 6e999092a..18ed22cac 100644 --- a/tests/unit/test_utils.py +++ b/tests/unit/test_utils.py @@ -238,7 +238,7 @@ def test_color_function_exists() -> None: # No color sets res = did.utils.color( "text", text_color=None, background=None, light=False, enabled=True) - assert res == "\033[0mtext\033[1;m" + assert res == "\033[0mtext\033[0m" # Disabled res = did.utils.color( "text", text_color=None, background=None, light=False, enabled=False) @@ -256,11 +256,11 @@ def test_color_function_exists() -> None: # Known color res = did.utils.color( "text", text_color="red", background=None, light=False, enabled=True) - assert res == "\033[0;31mtext\033[1;m" + assert res == "\033[0;31mtext\033[0m" # Light version res = did.utils.color( "text", text_color="red", background=None, light=True, enabled=True) - assert res == "\033[1;31mtext\033[1;m" + assert res == "\033[1;31mtext\033[0m" # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # strtobool