From c51d852bf4f439afa2cf7c9267018429142e3a7f Mon Sep 17 00:00:00 2001 From: Yash-Kavaiya Date: Thu, 6 Aug 2026 22:31:12 +0530 Subject: [PATCH] fix: Add Windows compatibility and JupyterKernelClient fallback --- src/colab_cli/commands/automation.py | 7 +++++-- src/colab_cli/console.py | 24 ++++++++++++++++-------- src/colab_cli/runtime.py | 2 +- 3 files changed, 22 insertions(+), 11 deletions(-) diff --git a/src/colab_cli/commands/automation.py b/src/colab_cli/commands/automation.py index 18c02a5..41dcfc3 100644 --- a/src/colab_cli/commands/automation.py +++ b/src/colab_cli/commands/automation.py @@ -102,8 +102,11 @@ def drivefs_hook(deserialize_msg, wsclient): state.history.log_event(s.name, "drive_auth_needed", {"uri": uri}) sys.stdout.write("Press Enter after you have granted access... ") sys.stdout.flush() - with open("/dev/tty") as tty: - tty.readline() + try: + with open("/dev/tty") as tty_file: + tty_file.readline() + except (OSError, FileNotFoundError): + sys.stdin.readline() typer.echo("[colab] Authorizing VM...") params["dryrun"] = "false" diff --git a/src/colab_cli/console.py b/src/colab_cli/console.py index 0766e1d..aeedf63 100644 --- a/src/colab_cli/console.py +++ b/src/colab_cli/console.py @@ -17,10 +17,14 @@ import os import signal import sys -import termios +try: + import termios + import tty +except ImportError: + termios = None + tty = None import threading import time -import tty from urllib.parse import urlparse import websocket @@ -133,8 +137,8 @@ def connect_console(session: SessionState): ws_url = f"{ws_scheme}://{parsed.netloc}/colab/tty?colab-runtime-proxy-token={session.token}" is_tty = sys.stdin.isatty() - fd = sys.stdin.fileno() if is_tty else None - old_settings = termios.tcgetattr(fd) if is_tty else None + fd = sys.stdin.fileno() if (is_tty and hasattr(sys.stdin, "fileno")) else None + old_settings = termios.tcgetattr(fd) if (is_tty and termios and fd is not None) else None ws = websocket.WebSocketApp( url=ws_url, @@ -151,8 +155,10 @@ def handle_sigwinch(signum, frame): try: if is_tty: - tty.setraw(fd, termios.TCSANOW) - signal.signal(signal.SIGWINCH, handle_sigwinch) + if tty and termios and fd is not None: + tty.setraw(fd, termios.TCSANOW) + if hasattr(signal, "SIGWINCH"): + signal.signal(signal.SIGWINCH, handle_sigwinch) # This is a blocking call until the connection is closed ws.run_forever() @@ -166,7 +172,9 @@ def handle_sigwinch(signum, frame): finally: if is_tty: # Always ensure the terminal is restored to its original state - termios.tcsetattr(fd, termios.TCSANOW, old_settings) + if termios and old_settings is not None and fd is not None: + termios.tcsetattr(fd, termios.TCSANOW, old_settings) # Restore the default signal handler for resize - signal.signal(signal.SIGWINCH, signal.SIG_DFL) + if hasattr(signal, "SIGWINCH"): + signal.signal(signal.SIGWINCH, signal.SIG_DFL) print("\r\nConnection closed.") diff --git a/src/colab_cli/runtime.py b/src/colab_cli/runtime.py index 5ebc262..bcd3cd6 100644 --- a/src/colab_cli/runtime.py +++ b/src/colab_cli/runtime.py @@ -115,7 +115,7 @@ def kernel_client(self): }, ) else: - self._kernel_client = jupyter_kernel_client.KernelClient( + self._kernel_client = jupyter_kernel_client.JupyterKernelClient( server_url=self.url, token=self.token, kernel_id=self.kernel_id,