Skip to content

fix device_utils#16

Merged
tmunzer-AIDE merged 15 commits intomainfrom
websocket-client-v2
Mar 15, 2026
Merged

fix device_utils#16
tmunzer-AIDE merged 15 commits intomainfrom
websocket-client-v2

Conversation

@tmunzer-AIDE
Copy link
Collaborator

No description provided.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR refactors device_utils to make WebSocket-based device utility functions non-blocking by running WebSocket connections in background threads. It also removes old duplicate module files that have been superseded by the __tools internal modules, and converts several incorrectly-marked async functions to synchronous.

Changes:

  • Refactored WebSocketWrapper.start() to run WebSocket connections in the background (run_in_background=True), with UtilResponse gaining receive(), wait(), done, disconnect(), context manager, and __await__ support for flexible consumption patterns.
  • Removed 9 old top-level device_utils module files (tools.py, sessions.py, service_path.py, port.py, policy.py, ospf.py, dot1x.py, dhcp.py, bpdu.py, bgp.py) that duplicated functionality now in __tools.
  • Converted async functions (clear_error, clear_sessions, clear_hit_count) to synchronous, and added input validation for monitor_traffic.

Reviewed changes

Copilot reviewed 19 out of 19 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
src/mistapi/device_utils/__tools/__ws_wrapper.py Core refactor: non-blocking WS, new UtilResponse API (receive, wait, done, disconnect, context manager, await)
src/mistapi/device_utils/__tools/miscellaneous.py Added isinstance check for monitor_traffic URL response
src/mistapi/device_utils/__tools/bpdu.py async → sync
src/mistapi/device_utils/__tools/dot1x.py async → sync
src/mistapi/device_utils/__tools/policy.py async → sync
src/mistapi/device_utils/__tools/mac.py Comment change (adds await to commented code)
src/mistapi/device_utils/__tools/dns.py Comment change (adds await to commented code)
src/mistapi/device_utils/ap.py Removed TracerouteProtocol re-export
src/mistapi/device_utils/tools.py Deleted (old duplicate)
src/mistapi/device_utils/sessions.py Deleted (old duplicate)
src/mistapi/device_utils/service_path.py Deleted (old duplicate)
src/mistapi/device_utils/port.py Deleted (old duplicate)
src/mistapi/device_utils/policy.py Deleted (old duplicate)
src/mistapi/device_utils/ospf.py Deleted (old duplicate)
src/mistapi/device_utils/dot1x.py Deleted (old duplicate)
src/mistapi/device_utils/dhcp.py Deleted (old duplicate)
src/mistapi/device_utils/bpdu.py Deleted (old duplicate)
src/mistapi/device_utils/bgp.py Deleted (old duplicate)
README.md Updated documentation for new non-blocking API patterns

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

You can also share your feedback on Copilot code review. Take the survey.

…onous operations

- Updated clear_sessions, clear_mac_table, and clear_learned_mac functions to utilize WebSocketWrapper for handling API calls and WebSocket events.
- Enhanced logging for debugging purposes in various functions including ping, traceroute, and OSPF commands.
- Removed synchronous trigger handling and replaced it with asynchronous WebSocket handling across multiple device utility functions.
- Updated version number in uv.lock to 0.61.1.
- Fix SessionWithUrl to connect directly to the custom URL instead of
  subscribing to it as a channel on the standard stream endpoint
- Extract shared Node enum into __common.py to eliminate duplication
  across 7 device utility modules
- Add await timeout safety net to UtilResponse (bounded by max_duration)
- Reduce receive() poll interval from 1s to 0.1s for lower tail latency
- Remove redundant _closed.clear() in WebSocketWrapper.start()
- Unify tcpdump_expression guard to use `is not None` in remote_capture
- Fix CHANGELOG: correct channel class names, fix port_id keyword,
  remove duplicate version entries, reorder sections
- Improve README async example comments to clarify concurrency model
- Sanitize API token logging with _apitoken_sanitizer helper
- Fix test mocks to match current APIResponse.raw_data (uses .text)
- Update test for SessionWithUrl channel behavior
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR (v0.61.1) refactors the device_utils module to make all device utility functions non-blocking, adds async support via mistapi.arun(), fixes several bugs (swapped API calls in dot1x/mac, file handle leaks, thread-safety for token rotation), improves API token log sanitization, and consolidates duplicate Node enums into a shared __common module.

Changes:

  • Device utility functions now return UtilResponse immediately with background WebSocket streaming, supporting callbacks, generators, context managers, polling, and async await
  • New mistapi.arun() helper for running sync API calls in async contexts via asyncio.to_thread()
  • Consolidation of duplicate code: shared Node enum, centralized _apitoken_sanitizer, removal of legacy per-function modules in favor of __tools subpackage

Reviewed changes

Copilot reviewed 43 out of 44 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
src/mistapi/__api_session.py Extract _apitoken_sanitizer helper, replace inline token masking
src/mistapi/__api_request.py Add thread lock for token rotation, fix file handle leak in mist_post_file
src/mistapi/__api_response.py Use response.text instead of str(response.content) for raw_data
src/mistapi/__init__.py Add arun() async helper
src/mistapi/device_utils/__tools/__ws_wrapper.py Major refactor: non-blocking UtilResponse with queue, start_with_trigger, background threading
src/mistapi/device_utils/__tools/__common.py New shared Node enum
src/mistapi/device_utils/__tools/*.py Refactor to use start_with_trigger, shared Node, improved logging
src/mistapi/device_utils/{ap,ex,srx,ssr}.py Update re-exports, rename OSPF functions, add sessions
src/mistapi/device_utils/{bgp,bpdu,...}.py (top-level) Deleted legacy modules
src/mistapi/websockets/session.py Fix SessionWithUrl to use _build_ws_url() override
README.md, CHANGELOG.md Document new async/non-blocking features
Version files Bump to 0.61.1

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

You can also share your feedback on Copilot code review. Take the survey.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR bumps the version to 0.61.1 and introduces several improvements: non-blocking device utilities with a new start_with_trigger pattern, an arun() async helper, consolidated Node enum, API token log sanitization, thread-safety for token rotation, and file handle leak fixes.

Changes:

  • Device utility functions are now non-blocking — trigger + WebSocket runs in background threads, returning a UtilResponse immediately with receive(), wait(), done, disconnect(), and await support
  • New mistapi.arun() async helper wraps sync API calls in asyncio.to_thread(), plus _apitoken_sanitizer for consistent token masking and file handle leak fix in mist_post_file
  • Consolidation of duplicated Node enum into __common.py, renaming of OSPF exports (e.g. showDatabaseretrieveOspfDatabase), addition of sessions/OSPF summary to SSR/SRX modules, and removal of legacy per-function module files

Reviewed changes

Copilot reviewed 43 out of 44 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
src/mistapi/__api_request.py Add _apitoken_sanitizer, _token_lock for thread-safe rotation, fix file handle leak
src/mistapi/__api_session.py Use _apitoken_sanitizer throughout token logging
src/mistapi/__api_response.py Use response.text instead of str(response.content) for raw_data
src/mistapi/__init__.py Add arun() async helper
src/mistapi/device_utils/__tools/__ws_wrapper.py Non-blocking UtilResponse with queue/events, start_with_trigger method
src/mistapi/device_utils/__tools/__common.py New shared Node enum
src/mistapi/device_utils/__tools/*.py Refactor to use start_with_trigger, import shared Node, rename apissessionapisession
src/mistapi/device_utils/{ssr,srx}.py Add sessions/OSPF summary exports, rename OSPF aliases
src/mistapi/device_utils/{bgp,bpdu,dhcp,...}.py Remove legacy per-function modules (moved to __tools/)
src/mistapi/websockets/session.py Fix SessionWithUrl to use _build_ws_url() instead of passing URL as channel
README.md, CHANGELOG.md Document new features, fix class name references
pyproject.toml, uv.lock, __version.py, sle.py Version bump to 0.61.1
tests/unit/test_*.py Update tests for raw_data and SessionWithUrl changes

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

You can also share your feedback on Copilot code review. Take the survey.

self._count: int = 0
self._apitoken: list[str] = []
self._apitoken_index: int = -1
self._token_lock: threading.Lock = threading.Lock()
- Add _VT100Screen class and ANSI escape stripping in WebSocketWrapper
for rendering screen-based output (top, monitor interface)
- Uncomment and refactor top_command() to use start_with_trigger pattern
- Export topCommand from device_utils.ex and device_utils.srx
- Handle binary WebSocket frames in _MistWebsocket._handle_message
(null byte stripping, bytes→str decode, TypeError catch)
- Fix first_message_timeout stop to check timer is active before stopping
- Update README with new functions and print flush examples
- Add unit tests for VT100 screen, ANSI stripping, and binary frames
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR bumps mistapi from 0.61.0 to 0.61.1, introducing non-blocking device utilities, async support via mistapi.arun(), VT100 terminal emulation for screen-based command output, binary WebSocket frame handling, and various refactors including consolidating Node enums, renaming OSPF exports, token sanitization improvements, and file handle leak fixes.

Changes:

  • Device utility functions now run trigger + WebSocket in background threads, returning UtilResponse immediately with receive(), wait(), await, and context manager support
  • New mistapi.arun() async helper, VT100 screen buffer for terminal output, binary frame decoding in WebSocket client, and thread-safe API token rotation
  • Consolidation of duplicate Node enums into __common.py, deletion of legacy per-function modules, and renaming of OSPF public exports

Reviewed changes

Copilot reviewed 46 out of 48 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
src/mistapi/__init__.py Adds arun() async helper
src/mistapi/__api_request.py Adds _apitoken_sanitizer, thread-safe token rotation, file handle leak fix
src/mistapi/__api_session.py Uses _apitoken_sanitizer for log masking
src/mistapi/__api_response.py Uses response.text instead of str(response.content)
src/mistapi/device_utils/__tools/__ws_wrapper.py Adds _VT100Screen, ANSI stripping, non-blocking start()/start_with_trigger(), enhanced UtilResponse
src/mistapi/device_utils/__tools/__common.py New shared Node enum
src/mistapi/device_utils/__tools/*.py Refactored to use start_with_trigger() pattern
src/mistapi/device_utils/{srx,ssr,ex}.py Updated exports, renamed OSPF functions, added topCommand/sessions
src/mistapi/device_utils/{tools,sessions,port,...}.py Deleted legacy per-function public modules
src/mistapi/websockets/__ws_client.py Handles binary WebSocket frames
src/mistapi/websockets/session.py SessionWithUrl uses _build_ws_url() instead of channels
tests/unit/test_ws_wrapper.py New tests for VT100 screen and ANSI stripping
tests/unit/test_websocket_client.py Tests for binary frame handling
README.md, CHANGELOG.md Documentation updates
Version files Bump to 0.61.1

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

You can also share your feedback on Copilot code review. Take the survey.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR (v0.61.1) is a significant refactor of the device_utils module, making all device utility functions non-blocking, adding async support via mistapi.arun(), introducing interactive shell sessions, and consolidating the Node enum into a shared __common module.

Changes:

  • All device utility functions now use start_with_trigger() to run API calls and WebSocket streams in background threads, returning UtilResponse immediately with support for generators, await, and context managers
  • New ShellSession class and interactive_shell() for SSH-over-WebSocket access to EX/SRX devices, plus new mistapi.arun() async helper
  • Refactoring: consolidated duplicate Node enums into __common.py, renamed OSPF exports (e.g., showDatabaseretrieveOspfDatabase), removed legacy top-level modules (e.g., device_utils/tools.py), added VT100 screen emulator, fixed file handle leaks, added thread-safety to token rotation

Reviewed changes

Copilot reviewed 48 out of 50 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
src/mistapi/__init__.py Added arun() async helper
src/mistapi/__api_request.py Token sanitizer, thread-safe rotation, file handle leak fix
src/mistapi/__api_session.py Use _apitoken_sanitizer throughout
src/mistapi/__api_response.py Use response.text instead of str(response.content)
src/mistapi/__version.py, pyproject.toml, uv.lock Version bump to 0.61.1, add sshkeyboard dep
src/mistapi/device_utils/__tools/__common.py New shared Node enum
src/mistapi/device_utils/__tools/__ws_wrapper.py VT100 screen emulator, non-blocking start()/start_with_trigger(), enhanced UtilResponse
src/mistapi/device_utils/__tools/shell.py New ShellSession and interactive_shell()
src/mistapi/device_utils/__tools/*.py Refactored to use start_with_trigger() pattern
src/mistapi/device_utils/{ap,ex,srx,ssr}.py Updated exports, renamed OSPF functions, added shell/sessions
src/mistapi/device_utils/*.py (deleted) Removed legacy top-level modules
src/mistapi/websockets/session.py SessionWithUrl stores URL separately, overrides _build_ws_url()
src/mistapi/websockets/__ws_client.py Handle binary WebSocket frames
tests/unit/*.py New tests for shell, ws_wrapper; updated existing tests
README.md, CHANGELOG.md Comprehensive documentation updates

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

You can also share your feedback on Copilot code review. Take the survey.

Comment on lines +52 to 59
return WebSocketWrapper(apisession, util_response).start_with_trigger(
trigger_fn=lambda: devices.clearSiteDevicePolicyHitCount(
apisession,
site_id=site_id,
device_id=device_id,
body={"policy_name": policy_name},
),
)
def _ws_factory(trigger):
if isinstance(trigger.data, dict) and "url" in trigger.data:
return SessionWithUrl(apisession, url=trigger.data.get("url", ""))
LOGGER.error("Top command command did not return a valid URL: %s", trigger.data)
Comment on lines +329 to +344
elif key == "up":
k = "\x00\x1b[A"
elif key == "right":
k = "\x00\x1b[C"
elif key == "down":
k = "\x00\x1b[B"
elif key == "left":
k = "\x00\x1b[D"
elif key == "backspace":
k = "\x00\x7f"
else:
k = key
data = f"\x00{k}"
data_bytes = bytearray()
data_bytes.extend(map(ord, data))
session.send(bytes(data_bytes))
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR bumps the version to 0.61.1 and introduces several significant changes: non-blocking device utilities with UtilResponse supporting generators/await/callbacks, a new interactive SSH shell feature, arun() async helper, refactored internal modules (consolidating Node enum, renaming OSPF functions), token sanitization improvements, thread-safety for token rotation, file handle leak fix, VT100 screen buffer for terminal output, and binary WebSocket frame handling.

Changes:

  • Device utilities are now non-blocking: trigger + WebSocket run in background threads, UtilResponse supports receive(), wait(), await, and context manager patterns
  • New ShellSession and interactive_shell() for SSH-over-WebSocket access to EX/SRX devices, plus arun() async helper
  • Refactored internals: consolidated Node enum to __common.py, renamed OSPF exports, fixed file handle leaks, added thread-safe token rotation, improved log sanitization

Reviewed changes

Copilot reviewed 48 out of 50 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
src/mistapi/__init__.py Added arun() async helper
src/mistapi/__api_request.py Added _apitoken_sanitizer, thread-safe token rotation, file handle leak fix
src/mistapi/__api_session.py Use _apitoken_sanitizer for log masking
src/mistapi/__api_response.py Use response.text instead of str(response.content) for raw_data
src/mistapi/device_utils/__tools/__ws_wrapper.py Major rewrite: VT100 screen, ANSI stripping, non-blocking start(), start_with_trigger(), enhanced UtilResponse
src/mistapi/device_utils/__tools/__common.py New shared Node enum
src/mistapi/device_utils/__tools/shell.py New ShellSession, create_shell_session, interactive_shell
src/mistapi/device_utils/__tools/*.py Refactored to use start_with_trigger() pattern, consolidated Node import
src/mistapi/device_utils/{ex,srx,ssr}.py Updated exports: renamed OSPF functions, added shell/sessions/topCommand
src/mistapi/device_utils/*.py (deleted) Removed legacy function-based modules (bgp, bpdu, dhcp, etc.)
src/mistapi/websockets/session.py SessionWithUrl stores URL separately, overrides _build_ws_url()
src/mistapi/websockets/__ws_client.py Handle binary WebSocket frames
tests/unit/* New tests for shell, VT100 screen, binary frames; updated API response tests
pyproject.toml, uv.lock Version bump, added sshkeyboard dependency
README.md, CHANGELOG.md Documentation updates

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

You can also share your feedback on Copilot code review. Take the survey.

Comment on lines +350 to +355
listen_keyboard(
on_release=_on_key_release,
delay_second_char=0,
delay_other_chars=0,
lower=False,
)
Comment on lines +181 to +184
data = bytearray()
data.extend(map(ord, f"\x00{text}"))
self.send(bytes(data))

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR (v0.61.1) is a significant refactor of the mistapi device utilities module. It makes all device utility functions non-blocking by running triggers and WebSocket streams in background threads, adds VT100 terminal emulation for screen-based commands, introduces interactive SSH shell support for EX/SRX devices, adds an arun() async helper, and consolidates duplicate Node enums into a shared __common.py module. Several legacy wrapper modules are deleted in favor of the __tools implementations.

Changes:

  • Device utility functions refactored to be non-blocking with new start_with_trigger() pattern, UtilResponse enhanced with receive(), wait(), disconnect(), and __await__ support
  • New ShellSession and interactive_shell() for SSH-over-WebSocket, new _VT100Screen for terminal emulation, new arun() async helper
  • Various fixes: binary WebSocket frame handling, file handle leak in mist_post_file, thread-safe token rotation, raw_data using response.text instead of str(response.content)

Reviewed changes

Copilot reviewed 48 out of 50 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
src/mistapi/device_utils/__tools/__ws_wrapper.py Core refactor: added _VT100Screen, ANSI stripping, UtilResponse enhancements, start_with_trigger()
src/mistapi/device_utils/__tools/shell.py New ShellSession and interactive_shell() for SSH-over-WebSocket
src/mistapi/device_utils/__tools/__common.py New shared Node enum
src/mistapi/device_utils/__tools/*.py Refactored to use start_with_trigger(), consolidated Node import
src/mistapi/device_utils/{ex,srx,ssr}.py Updated exports, added shell/topCommand/OSPF renames
src/mistapi/__init__.py Added arun() async helper
src/mistapi/__api_request.py Token sanitizer, thread-safe rotation, file handle leak fix
src/mistapi/__api_response.py raw_data changed from str(content) to response.text
src/mistapi/__api_session.py Use _apitoken_sanitizer throughout
src/mistapi/websockets/__ws_client.py Binary frame handling
src/mistapi/websockets/session.py SessionWithUrl fix: store URL separately, override _build_ws_url
src/mistapi/device_utils/{bgp,bpdu,dhcp,dot1x,ospf,policy,port,sessions,service_path,tools}.py Deleted legacy wrapper modules
tests/unit/test_ws_wrapper.py New tests for VT100 screen and ANSI stripping
tests/unit/test_shell.py New tests for ShellSession
tests/unit/test_websocket_client.py Tests for binary frame handling, SessionWithUrl fix
tests/unit/test_api_response.py Updated for raw_data change
README.md, CHANGELOG.md Documentation updates
pyproject.toml, uv.lock Version bump, sshkeyboard dependency

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

You can also share your feedback on Copilot code review. Take the survey.

mode changes are silently ignored.
"""

def __init__(self, rows: int = 80, cols: int = 200) -> None:
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR (v0.61.1) is a substantial refactoring of the device_utils module, making all device utility functions non-blocking by running API triggers and WebSocket streams in background threads. It also adds VT100 terminal emulation, interactive SSH shell support, async helpers, binary WebSocket frame handling, token sanitization improvements, and a file handle leak fix.

Changes:

  • All device utility functions now return UtilResponse immediately (non-blocking), with a new start_with_trigger pattern replacing the old synchronous trigger-then-stream approach. Duplicate Node enums consolidated into __common.py. OSPF functions renamed (showDatabaseretrieveOspfDatabase, etc.). Legacy function-based modules deleted.
  • New features: ShellSession/interactiveShell() for SSH-over-WebSocket, _VT100Screen for screen-based command rendering, mistapi.arun() async helper, binary frame support in _handle_message, _apitoken_sanitizer for log safety, thread-safe token rotation, file handle leak fix in mist_post_file.
  • UtilResponse enhanced with receive() generator, wait(), done property, disconnect(), context manager, and __await__ support.

Reviewed changes

Copilot reviewed 48 out of 50 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
src/mistapi/device_utils/__tools/__ws_wrapper.py Core refactoring: added _VT100Screen, ANSI stripping, UtilResponse with async/generator/context manager support, start_with_trigger method
src/mistapi/device_utils/__tools/shell.py New ShellSession class and interactive_shell() for SSH-over-WebSocket
src/mistapi/device_utils/__tools/__common.py New shared Node enum
src/mistapi/device_utils/__tools/*.py Refactored to use start_with_trigger, consolidated Node, renamed apissessionapisession
src/mistapi/device_utils/{ex,srx,ssr}.py Updated exports: renamed OSPF functions, added shell/sessions/topCommand
src/mistapi/device_utils/*.py (deleted) Removed legacy function-based modules (bgp, ospf, port, dhcp, etc.)
src/mistapi/__init__.py Added arun() async helper
src/mistapi/__api_request.py Added _apitoken_sanitizer, thread-safe token rotation, file handle leak fix
src/mistapi/__api_session.py Uses _apitoken_sanitizer for log messages
src/mistapi/__api_response.py raw_data now uses response.text instead of str(response.content)
src/mistapi/websockets/__ws_client.py Binary frame handling in _handle_message
src/mistapi/websockets/session.py SessionWithUrl stores URL separately, overrides _build_ws_url
tests/unit/test_ws_wrapper.py New tests for ANSI stripping and VT100 screen rendering
tests/unit/test_shell.py New tests for ShellSession and create_shell_session
tests/unit/test_websocket_client.py Tests for binary frame handling
tests/unit/test_api_response.py Updated for raw_data change
pyproject.toml, uv.lock Version bump, added sshkeyboard dependency
README.md, CHANGELOG.md Documentation updates

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

You can also share your feedback on Copilot code review. Take the survey.

@tmunzer-AIDE
Copy link
Collaborator Author

Code review

Found 1 issue:

  1. Race condition in ShellSession.connected property: disconnect() sets self._ws = None (line 164) without any lock, while connected (line 169) performs a non-atomic self._ws is not None and self._ws.connected check. The _reader thread in interactive_shell() calls session.connected in a tight loop (line 311). If disconnect() runs between the is not None check (True) and the .connected attribute access, self._ws is now None, raising AttributeError. Fix: capture self._ws in a local variable before checking, or add a threading lock.

def disconnect(self) -> None:
"""Close the WebSocket connection."""
if self._ws:
try:
self._ws.close()
except Exception:
pass
self._ws = None
@property
def connected(self) -> bool:
"""True if the WebSocket is currently connected."""
return self._ws is not None and self._ws.connected

🤖 Generated with Claude Code

- If this code review was useful, please react with 👍. Otherwise, react with 👎.

@tmunzer-AIDE tmunzer-AIDE merged commit ac62836 into main Mar 15, 2026
7 checks passed
@tmunzer-AIDE tmunzer-AIDE deleted the websocket-client-v2 branch March 15, 2026 14:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants