Skip to content

Commit f030ec1

Browse files
committed
fix comments
1 parent 99b8f44 commit f030ec1

3 files changed

Lines changed: 62 additions & 12 deletions

File tree

CHANGELOG.md

Lines changed: 55 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,13 @@
33

44
**Released**: March 15, 2026
55

6-
This release improves async support with a new `arun()` helper and makes the Device Utilities module fully non-blocking.
6+
This release improves async support with a new `arun()` helper, makes the Device Utilities module fully non-blocking, adds VT100 terminal emulation for screen-based commands, and introduces interactive SSH shell access for EX/SRX devices. (PR #16)
77

88
---
99

1010
### 1. NEW FEATURES
1111

12-
#### **`mistapi.arun()` - Async Helper**
12+
#### **`mistapi.arun()` Async Helper**
1313
New helper function to run any sync mistapi function without blocking the event loop. Wraps the function call in `asyncio.to_thread()` so blocking HTTP requests run in a thread pool.
1414

1515
```python
@@ -28,6 +28,33 @@ async def main():
2828
asyncio.run(main())
2929
```
3030

31+
#### **Interactive SSH Shell** (`device_utils.ex` / `device_utils.srx`)
32+
New `interactiveShell()` and `createShellSession()` functions for SSH-over-WebSocket access to EX and SRX devices.
33+
34+
- `interactiveShell()` — takes over the terminal for human SSH access (uses `sshkeyboard`)
35+
- `createShellSession()` — returns a `ShellSession` object for programmatic send/recv
36+
- `ShellSession` — bidirectional WebSocket session with `send()`, `recv()`, `resize()`, context manager support
37+
38+
```python
39+
from mistapi.device_utils import ex
40+
41+
# Interactive (human at the keyboard)
42+
ex.interactiveShell(apisession, site_id, device_id)
43+
44+
# Programmatic
45+
with ex.createShellSession(apisession, site_id, device_id) as session:
46+
session.send_text("show version\r\n")
47+
import time; time.sleep(3)
48+
while (data := session.recv(timeout=0.5)):
49+
print(data.decode("utf-8", errors="replace"), end="")
50+
```
51+
52+
#### **`topCommand`** (`device_utils.ex` / `device_utils.srx`)
53+
New `topCommand()` function to stream `top` output from EX and SRX devices. Uses VT100 screen-buffer rendering for proper in-place display.
54+
55+
#### **VT100 Terminal Emulation**
56+
Added ANSI escape stripping and a minimal VT100 screen-buffer renderer for device command output. Stream-mode commands (ping, traceroute) have ANSI codes stripped automatically. Screen-mode commands (top, monitor interface) are rendered through a virtual terminal buffer.
57+
3158
---
3259

3360
### 2. IMPROVEMENTS
@@ -63,6 +90,32 @@ for msg in response.receive():
6390
await response
6491
```
6592

93+
#### **Binary WebSocket Frame Support**
94+
`_MistWebsocket._handle_message()` now handles binary frames (strips null bytes, decodes UTF-8 with replacement characters).
95+
96+
#### **Trigger-Only Commands Run Synchronously**
97+
Fire-and-forget device commands (e.g., `clearMacTable`, `clearBpduError`, `clearHitCount`) that don't require a WebSocket stream now run the API trigger synchronously, ensuring `trigger_api_response` is immediately available on the returned `UtilResponse`.
98+
99+
#### **SRX Function Renames**
100+
SRX and SSR OSPF/session functions renamed for clarity:
101+
- `showDatabase``retrieveOspfDatabase`
102+
- `showNeighbors``retrieveOspfNeighbors`
103+
- `showInterfaces``retrieveOspfInterfaces`
104+
- New: `retrieveOspfSummary`, `retrieveSessions`, `clearSessions`
105+
106+
---
107+
108+
### 3. BUG FIXES
109+
110+
- Fixed double-space typo in API token privilege mismatch error message
111+
- Fixed `first_message_timeout` timer stop to check timer is active before stopping
112+
113+
---
114+
115+
### 4. DEPENDENCIES
116+
117+
- Added `sshkeyboard>=2.3.1` (for `interactiveShell()`)
118+
66119
---
67120

68121
## Version 0.61.0 (March 2026)

src/mistapi/__api_request.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ def _apitoken_sanitizer(apitoken: str) -> str:
4646
str
4747
Substring of the API token to be used in the logs
4848
"""
49+
if len(apitoken) <= 16:
50+
return "***hidden***"
4951
return f"{apitoken[:4]}...{apitoken[-4:]}"
5052

5153

src/mistapi/device_utils/__tools/shell.py

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -178,9 +178,7 @@ def send(self, data: bytes) -> None:
178178

179179
def send_text(self, text: str) -> None:
180180
"""Send a text string as binary data to the device shell."""
181-
data = bytearray()
182-
data.extend(map(ord, f"\x00{text}"))
183-
self.send(bytes(data))
181+
self.send(f"\x00{text}".encode("utf-8"))
184182

185183
def recv(self, timeout: float = 0.1) -> bytes | None:
186184
"""
@@ -316,8 +314,8 @@ def _reader():
316314
sys.stdout.buffer.write(data)
317315
sys.stdout.buffer.flush()
318316

319-
def _on_key_release(key: str) -> None:
320-
"""Handle a key release event from sshkeyboard."""
317+
def _on_key_press(key: str) -> None:
318+
"""Handle a key press event from sshkeyboard."""
321319
if not session.connected:
322320
return
323321
if key == "enter":
@@ -338,17 +336,14 @@ def _on_key_release(key: str) -> None:
338336
k = "\x7f"
339337
else:
340338
k = key
341-
data = f"\x00{k}"
342-
data_bytes = bytearray()
343-
data_bytes.extend(map(ord, data))
344-
session.send(bytes(data_bytes))
339+
session.send(f"\x00{k}".encode("utf-8"))
345340

346341
reader_thread = threading.Thread(target=_reader, daemon=True)
347342
reader_thread.start()
348343

349344
try:
350345
listen_keyboard(
351-
on_release=_on_key_release,
346+
on_press=_on_key_press,
352347
delay_second_char=0,
353348
delay_other_chars=0,
354349
lower=False,

0 commit comments

Comments
 (0)