Skip to content

Commit 48fdd16

Browse files
committed
fix: support windows import for markets tui
1 parent 8022c93 commit 48fdd16

2 files changed

Lines changed: 61 additions & 3 deletions

File tree

src/hl_cli/cli/markets_tui.py

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
11
import contextlib
22
import json
3-
import select
43
import sys
5-
import termios
64
import time
7-
import tty
85
from itertools import cycle
96
from typing import Callable, Iterator, Literal, Optional
107

@@ -69,6 +66,13 @@ def _raw_tty_mode() -> Iterator[bool]:
6966
if not sys.stdin.isatty():
7067
yield False
7168
return
69+
if sys.platform == "win32":
70+
yield True
71+
return
72+
73+
import termios
74+
import tty
75+
7276
fd = sys.stdin.fileno()
7377
old = termios.tcgetattr(fd)
7478
try:
@@ -81,6 +85,35 @@ def _raw_tty_mode() -> Iterator[bool]:
8185
def _read_key(timeout: float = 0.0) -> Optional[str]:
8286
if not sys.stdin.isatty():
8387
return None
88+
if sys.platform == "win32":
89+
return _read_windows_key(timeout)
90+
return _read_posix_key(timeout)
91+
92+
93+
def _read_windows_key(timeout: float = 0.0) -> Optional[str]:
94+
import msvcrt
95+
96+
deadline = time.time() + timeout
97+
while not msvcrt.kbhit():
98+
if timeout <= 0 or time.time() >= deadline:
99+
return None
100+
time.sleep(min(0.01, max(0.0, deadline - time.time())))
101+
102+
first = msvcrt.getwch()
103+
if first not in {"\x00", "\xe0"}:
104+
return first
105+
106+
second = msvcrt.getwch()
107+
if second == "H":
108+
return "\x1b[A"
109+
if second == "P":
110+
return "\x1b[B"
111+
return first + second
112+
113+
114+
def _read_posix_key(timeout: float = 0.0) -> Optional[str]:
115+
import select
116+
84117
ready, _, _ = select.select([sys.stdin], [], [], timeout)
85118
if not ready:
86119
return None

tests/test_windows_imports.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import builtins
2+
import importlib
3+
import sys
4+
import unittest
5+
from unittest.mock import patch
6+
7+
8+
class WindowsImportTests(unittest.TestCase):
9+
def test_markets_tui_import_does_not_require_posix_tty_modules(self):
10+
original_import = builtins.__import__
11+
12+
def import_without_posix_tty(name, *args, **kwargs):
13+
if name in {"termios", "tty"}:
14+
raise ModuleNotFoundError(f"No module named {name!r}")
15+
return original_import(name, *args, **kwargs)
16+
17+
sys.modules.pop("hl_cli.cli.markets_tui", None)
18+
with patch.object(builtins, "__import__", side_effect=import_without_posix_tty):
19+
module = importlib.import_module("hl_cli.cli.markets_tui")
20+
21+
self.assertTrue(hasattr(module, "run_markets_tui"))
22+
23+
24+
if __name__ == "__main__":
25+
unittest.main()

0 commit comments

Comments
 (0)