diff options
| author | blasty <peter@haxx.in> | 2026-08-21 12:09:12 +0200 |
|---|---|---|
| committer | blasty <peter@haxx.in> | 2026-08-21 12:09:21 +0200 |
| commit | 9541043c9dee7973c140159b3af561c6d0405e9e (patch) | |
| tree | 1395ffadb7dd44b4b2acc3b1f2348fa367667dc8 /tests/test_kittygfx.py | |
| parent | splash: give the logo a placement id so re-anchoring replaces, not stacks (diff) | |
| parent | Switch to ida-nexus (diff) | |
| download | ida-tui-9541043c9dee7973c140159b3af561c6d0405e9e.tar.gz ida-tui-9541043c9dee7973c140159b3af561c6d0405e9e.tar.xz ida-tui-9541043c9dee7973c140159b3af561c6d0405e9e.zip | |
Merge PR #1 from mrexodia: Windows support and auto-refresh on events
https://github.com/blasty/ida-tui/pull/1 — from the ida-nexus (né
ida-codemode) maintainer: kitty-graphics fallback for platforms without
termios, Ctrl+R view refresh, typed remote operations through ida_nexus
RemoteModule, live auto-refresh from other clients' IDB events (upstream
item 7), discard-without-save (item 6), and the ida-nexus 0.7.0 rename.
tests/test_kittygfx.py is the union of both sides' files: our escape-
construction checks plus the PR's cross-platform fallback checks.
Diffstat (limited to 'tests/test_kittygfx.py')
| -rw-r--r-- | tests/test_kittygfx.py | 59 |
1 files changed, 59 insertions, 0 deletions
diff --git a/tests/test_kittygfx.py b/tests/test_kittygfx.py index b12817d..38d361c 100644 --- a/tests/test_kittygfx.py +++ b/tests/test_kittygfx.py @@ -4,11 +4,16 @@ The splash re-anchors itself on every progress note, so the escape it sends has to be a REPLACEMENT, not another copy. That is one key (``p``) and it is invisible in every screenshot, which is exactly why it needs a test. + +Also the cross-platform contract: graphics are optional everywhere, so a +missing ``termios`` (native Windows) or a failing terminal probe must disable +the splash, never prevent TUI startup. """ #: pure stdlib escape-construction checks; no IDA, no Textual. #: Read by tests/run.py (--fast skips every NEEDS_IDA file). NEEDS_IDA = False +import builtins import os import re import sys @@ -58,7 +63,61 @@ def keys(cmd): return dict(kv.split("=", 1) for kv in cmd.split(",") if "=" in kv) +def t_no_termios_falls_back(): + """Native Windows has no termios; the splash must simply use ANSI art.""" + original_import = builtins.__import__ + + def without_termios(name, *args, **kwargs): + if name == "termios": + raise ModuleNotFoundError("No module named 'termios'") + return original_import(name, *args, **kwargs) + + builtins.__import__ = without_termios + try: + check("missing termios disables graphics", kittygfx._query_tty(0) is False) + except Exception as exc: # the original Windows startup crash + check("missing termios does not escape", False, + f"{type(exc).__name__}: {exc}") + finally: + builtins.__import__ = original_import + + +def t_probe_failure_is_never_fatal(): + """Even an unexpected platform/probe error cannot prevent TUI startup.""" + original_query = kittygfx._query_tty + original_stdout = sys.__stdout__ + original_supported = kittygfx._supported + old_env = os.environ.pop("IDATUI_KITTY", None) + + class FakeTty: + def isatty(self): + return True + + def broken_query(): + raise RuntimeError("terminal API failed") + + try: + sys.__stdout__ = FakeTty() + kittygfx._query_tty = broken_query + kittygfx._supported = None + check("probe exception disables graphics", kittygfx.supported() is False) + check("failed result is cached", kittygfx.supported() is False) + except Exception as exc: + check("probe exception does not escape", False, + f"{type(exc).__name__}: {exc}") + finally: + kittygfx._query_tty = original_query + kittygfx._supported = original_supported + sys.__stdout__ = original_stdout + if old_env is not None: + os.environ["IDATUI_KITTY"] = old_env + + def main() -> int: + # -- graphics stay optional on every platform ---------------------------- # + t_no_termios_falls_back() + t_probe_failure_is_never_fatal() + kittygfx._uploaded[kittygfx.LOGO_ID] = (768, 801) # pretend it's uploaded # -- the bug: anonymous placements STACK ------------------------------- # |
