From 4a67acc959f5ce81b0470048df3725588b4bd4af Mon Sep 17 00:00:00 2001 From: SunneV Date: Tue, 30 Sep 2025 18:20:49 +0200 Subject: [PATCH] Resolved a `UnicodeEncodeError` that occurred on legacy Windows terminals. --- CHANGELOG.md | 6 +++++- pyproject.toml | 2 +- src/scriber/cli.py | 25 ++++++++++++++++++++++--- 3 files changed, 28 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3a70b9c..2cf07d6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,11 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [1.1.2] - 2025-09-30 + +### Fixed +- Resolved a `UnicodeEncodeError` that occurred on legacy Windows terminals. The CLI now detects incompatible consoles and disables emoji characters in the output to prevent crashes, ensuring compatibility. + ## [1.1.1] - 2025-09-15 ### Added @@ -14,7 +19,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Refactored the internal configuration management from a dictionary to a `dataclass` (`ScriberConfig`). This improves type safety, code readability, and makes programmatic configuration more intuitive and less error-prone. - Enhanced the `exclude` configuration option to support `.gitignore`-style pattern matching. This allows for more precise rules, such as matching directories only (e.g., `build/`) or root-level files (e.g., `/config.yaml`). - ## [1.1.0] - 2025-09-15 ### Added diff --git a/pyproject.toml b/pyproject.toml index 06d2717..86f56ef 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "project-scriber" -version = "1.1.1" +version = "1.1.2" authors = [ { name="SunneV (Wojciech Mariusz CichoĊ„)", email="wojciech.m.cichon@gmail.com" }, ] diff --git a/src/scriber/cli.py b/src/scriber/cli.py index 1b979be..e689c64 100644 --- a/src/scriber/cli.py +++ b/src/scriber/cli.py @@ -34,14 +34,24 @@ class SimpleConsole: """A fallback console that mimics rich.Console with simple print statements.""" def print(self, message: Any = "") -> None: - """Strips rich markup and prints the message. + """Strips rich markup and prints the message, handling potential Unicode errors. + + This method attempts to print the message directly. If a UnicodeEncodeError + occurs, it falls back to encoding the message using the system's stdout + encoding, replacing any unsupported characters to prevent crashes. Args: message: The object or text to print. """ message_str = str(message) cleaned_message = re.sub(r'\[/?[a-zA-Z\s=]+\]', '', message_str) - print(cleaned_message) + try: + print(cleaned_message) + except UnicodeEncodeError: + safe_message = cleaned_message.encode( + sys.stdout.encoding, errors='replace' + ).decode(sys.stdout.encoding) + print(safe_message) def format_bytes(byte_count: int) -> str: @@ -285,7 +295,16 @@ def run_scriber(args: argparse.Namespace, console: Any, version: str, rich_avail def main() -> None: """Parses arguments and runs the appropriate command.""" if RICH_AVAILABLE: - console = Console() + # On Windows, the default console (cmd.exe) often doesn't support Unicode + # emojis. We detect this environment and disable emojis to prevent crashes, + # unless we are in a modern terminal like Windows Terminal. + is_legacy_windows = ( + sys.platform == "win32" + and not os.environ.get("WT_SESSION") + and not os.environ.get("TERMINUS_SUCKS") + and sys.stdout.encoding != "utf-8" + ) + console = Console(emoji=not is_legacy_windows) else: console = SimpleConsole()