Merge branch 'main' of https://git.revoluxiant.io.vn/revernomad17/arma-modlist-tools
This commit is contained in:
@@ -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.
|
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
|
||||||
|
|
||||||
`test_suite.py` uses a custom harness (no pytest/unittest dependency). Structure:
|
`test_suite.py` uses a custom harness (no pytest/unittest dependency). Structure:
|
||||||
|
|||||||
@@ -102,6 +102,8 @@ def fix_console_encoding() -> None:
|
|||||||
"""
|
"""
|
||||||
if not is_windows():
|
if not is_windows():
|
||||||
return
|
return
|
||||||
|
if sys.stdout is None or sys.stderr is None:
|
||||||
|
return
|
||||||
if sys.stdout.encoding and sys.stdout.encoding.lower() == "utf-8":
|
if sys.stdout.encoding and sys.stdout.encoding.lower() == "utf-8":
|
||||||
return
|
return
|
||||||
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding="utf-8", errors="replace")
|
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding="utf-8", errors="replace")
|
||||||
|
|||||||
@@ -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: _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 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)
|
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 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 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)
|
||||||
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
|
|||||||
Reference in New Issue
Block a user