This commit is contained in:
Tran G. (Revernomad) Khoa
2026-04-10 22:38:20 +07:00
3 changed files with 19 additions and 0 deletions

View File

@@ -147,6 +147,10 @@ get_language() # → "vi"
Minimum is Python **3.9**. All files that use `X | Y` union type annotations **must** have `from __future__ import annotations` as the first import. Without it, the `|` syntax raises `TypeError` at runtime on Python < 3.10. Every module in `arma_modlist_tools/` already has it; any new CLI script you add must include it too.
### `fix_console_encoding` — `None` stdout guard
When the GUI is launched via `pythonw.exe` (no console window), Python sets `sys.stdout` and `sys.stderr` to `None`. `fix_console_encoding()` must check `if sys.stdout is None or sys.stderr is None: return` **before** accessing `.encoding`, otherwise it raises `AttributeError: 'NoneType' object has no attribute 'encoding'`. This error surfaces in the GUI as *"Failed to load pipeline"* because `run.py` calls `fix_console_encoding()` at module level and the exception is caught by the pipeline import guard.
## Test Suite
`test_suite.py` uses a custom harness (no pytest/unittest dependency). Structure:

View File

@@ -102,6 +102,8 @@ def fix_console_encoding() -> None:
"""
if not is_windows():
return
if sys.stdout is None or sys.stderr is None:
return
if sys.stdout.encoding and sys.stdout.encoding.lower() == "utf-8":
return
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding="utf-8", errors="replace")

View File

@@ -2076,8 +2076,21 @@ test("compat: _read_os_release parses key=value pairs", _test_r
test("compat: _read_os_release returns {} when file missing", _test_read_os_release_handles_missing_file)
test("compat: _is_headless returns False when DISPLAY is set", _test_is_headless_with_display)
test("compat: _is_headless returns True when no display env vars", _test_is_headless_without_display)
def _test_fix_console_encoding_none_stdout():
"""fix_console_encoding is a no-op when sys.stdout is None (pythonw.exe)."""
original_stdout = sys.stdout
try:
with _patch("arma_modlist_tools.compat.is_windows", return_value=True):
sys.stdout = None
_compat_mod.fix_console_encoding() # must not raise
assert sys.stdout is None
finally:
sys.stdout = original_stdout
test("compat: fix_console_encoding is no-op on non-Windows", _test_fix_console_encoding_non_windows_noop)
test("compat: fix_console_encoding skips when stdout already UTF-8", _test_fix_console_encoding_already_utf8)
test("compat: fix_console_encoding is no-op when stdout is None", _test_fix_console_encoding_none_stdout)
# ---------------------------------------------------------------------------