Skip to content

Commit 75dcc2c

Browse files
fix: use ASCII fallbacks for Unicode symbols on Windows
On Windows terminals using cp1252 encoding, Unicode characters like ✓, ✗, and → cannot be encoded. This fix adds a _supports_unicode() check that falls back to ASCII-safe alternatives: - ✓ → [OK] - ✗ → [FAIL] - → → -> Fixes CI failure on Windows: UnicodeEncodeError with cp1252 codec
1 parent 98cb3e0 commit 75dcc2c

File tree

1 file changed

+24
-5
lines changed

1 file changed

+24
-5
lines changed

src/importguard/cli.py

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,25 @@
1212
from .models import ImportResult
1313

1414

15+
def _supports_unicode() -> bool:
16+
"""Check if the terminal supports Unicode output."""
17+
# Check if stdout encoding supports common Unicode characters
18+
try:
19+
encoding = getattr(sys.stdout, "encoding", None) or "ascii"
20+
# Try encoding our symbols
21+
"✓✗→".encode(encoding)
22+
return True
23+
except (UnicodeEncodeError, LookupError):
24+
return False
25+
26+
27+
# Use ASCII fallbacks on terminals that don't support Unicode (e.g., Windows cp1252)
28+
_UNICODE_OK = _supports_unicode()
29+
_CHECK = "✓" if _UNICODE_OK else "[OK]"
30+
_CROSS = "✗" if _UNICODE_OK else "[FAIL]"
31+
_ARROW = "→" if _UNICODE_OK else "->"
32+
33+
1534
def format_time(ms: float) -> str:
1635
"""Format time in milliseconds for display."""
1736
if ms >= 1000:
@@ -36,19 +55,19 @@ def print_result(
3655

3756
# Handle import failure specially
3857
if result.import_failed:
39-
print(f"{red} FAIL:{reset} {result.module} failed to import")
58+
print(f"{red}{_CROSS} FAIL:{reset} {result.module} failed to import")
4059
if result.error_message:
4160
# Indent error message lines
4261
for line in result.error_message.splitlines():
43-
print(f" {red}{reset} {line}")
62+
print(f" {red}{_ARROW}{reset} {line}")
4463
return
4564

4665
# Status line for successful import
4766
if result.passed:
48-
status = "✓"
67+
status = _CHECK
4968
color = green
5069
else:
51-
status = "✗ FAIL:"
70+
status = f"{_CROSS} FAIL:"
5271
color = red
5372

5473
time_str = format_time(result.total_ms)
@@ -66,7 +85,7 @@ def print_result(
6685

6786
# Print violations
6887
for violation in result.violations:
69-
print(f" {color}{reset} {violation}")
88+
print(f" {color}{_ARROW}{reset} {violation}")
7089

7190
# Print top imports (only if showing details)
7291
if result.imports and not quiet:

0 commit comments

Comments
 (0)