Skip to content

Conversation

@echarles
Copy link
Member

@echarles echarles commented Jan 16, 2026

Fixes #35

Copilot AI review requested due to automatic review settings January 16, 2026 14:29
@echarles echarles changed the title PORT - Changes to support talking to Colab from the JKC BACKPORT - Changes to support talking to Colab from the JKC Jan 16, 2026
Copy link

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 pull request adds support for the Jupyter Kernel Client to communicate with Google Colab by introducing a new JSON-based WebSocket subprotocol alongside the existing v1 binary protocol.

Changes:

  • Introduced JupyterSubprotocol enum to specify communication protocols (DEFAULT, V1, JSON)
  • Added JSON serialization/deserialization functions for Colab compatibility
  • Enhanced KernelWebSocketClient and WSSession to support multiple subprotocols
  • Modified KernelHttpManager to accept and forward custom headers
  • Added dependency-groups configuration for uv package manager
  • Updated test dependencies and added Makefile test target

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 14 comments.

Show a summary per file
File Description
pyproject.toml Added dependency-groups for uv, specified new test dependencies, and added test target configuration
jupyter_kernel_client/wsclient.py Introduced JupyterSubprotocol enum, added subprotocol parameter to WSSession and KernelWebSocketClient, implemented protocol-specific message serialization logic
jupyter_kernel_client/utils.py Added JSON serialization/deserialization functions for Colab support
jupyter_kernel_client/manager.py Added headers parameter support and updated User-Agent string
jupyter_kernel_client/client.py Added null check for manager in stop method
jupyter_kernel_client/init.py Exported JupyterSubprotocol enum
Makefile Added test target for running pytest

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

headers = {
"Accept": "application/json",
"Content-Type": "application/json",
"User-Agent": "Jupyter Kernel Client"
Copy link

Copilot AI Jan 16, 2026

Choose a reason for hiding this comment

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

The User-Agent header value was changed from "Jupyter kernels CLI" to "Jupyter Kernel Client". While this change is likely intentional to better reflect the library's name, it represents a breaking change that could impact server-side analytics, logging, or behavior that depends on the User-Agent string.

Suggested change
"User-Agent": "Jupyter Kernel Client"
"User-Agent": "Jupyter kernels CLI"

Copilot uses AI. Check for mistakes.
Comment on lines +132 to +145
[dependency-groups]
dev = [
{include-group = "test"}
]
test = [
"ipykernel>=6.31.0",
"jupyter-server>=2.17.0",
"numpy>=2.0.2",
"pandas>=2.3.3",
"pytest>=8.4.2",
"pytest-asyncio>=1.2.0",
"pytest-cov>=7.0.0",
"pytest-timeout>=2.4.0",
]
Copy link

Copilot AI Jan 16, 2026

Choose a reason for hiding this comment

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

The dependency-groups section duplicates and conflicts with the existing project.optional-dependencies.test section. The dependency-groups.test has different version constraints (e.g., ipykernel>=6.31.0 vs ipykernel without version, jupyter-server>=2.17.0 vs jupyter_server>=2.10,<3). This duplication can cause confusion about which dependencies to use and may lead to inconsistent test environments. Consider consolidating these or clarifying which should be used.

Copilot uses AI. Check for mistakes.
Comment on lines +480 to +481


Copy link

Copilot AI Jan 16, 2026

Choose a reason for hiding this comment

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

There are extra blank lines here. Line 480 appears to be unnecessary trailing whitespace, and line 481 adds an extra blank line. This violates code style conventions and may cause linting issues.

Suggested change

Copilot uses AI. Check for mistakes.
Comment on lines +474 to +475
token_param: String | None
The name of the token parameter to use.
Copy link

Copilot AI Jan 16, 2026

Choose a reason for hiding this comment

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

The docstring comment on line 474 incorrectly states "String | None" for the token_param type. However, there is no token_param parameter in the init method signature. This documentation appears to be erroneous or incomplete.

Suggested change
token_param: String | None
The name of the token parameter to use.

Copilot uses AI. Check for mistakes.

def deserialize_msg_from_ws_json(ws_msg):
"""Deserialize as JSON (for Colab)."""
return json.loads(ws_msg.encode('utf-8'))
Copy link

Copilot AI Jan 16, 2026

Choose a reason for hiding this comment

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

The deserialize_msg_from_ws_json function is calling encode on a parameter that is already bytes. According to the _on_message signature in wsclient.py (line 1247), the message parameter is already of type bytes. Calling encode on bytes will raise an AttributeError. The function should either accept a string and encode it, or accept bytes and decode it directly.

Suggested change
return json.loads(ws_msg.encode('utf-8'))
# `ws_msg` may be either `str` or `bytes` depending on the WebSocket client.
# If it's bytes, decode it to text before passing to json.loads.
if isinstance(ws_msg, bytes):
text = ws_msg.decode("utf-8")
else:
text = ws_msg
return json.loads(text)

Copilot uses AI. Check for mistakes.
Comment on lines 37 to 51
class JupyterSubprotocol(Enum):
"""JupyterSubprotocol specifies which subprotocol the KernelWebSocketClient should specifically
request when interacting with the Jupyter server.
"""

# Use the default subprotocol
# https://jupyter-server.readthedocs.io/en/latest/developers/websocket-protocols.html#default-websocket-protocol
DEFAULT = 0

# Use the v1.kernel.websocket.jupyter.org protocol
# https://jupyter-server.readthedocs.io/en/latest/developers/websocket-protocols.html#v1-kernel-websocket-jupyter-org-protocol
V1 = 1

# JSON is specifically for Colab (until we modify this library to actually have support for DEFAULT)
JSON = 2
Copy link

Copilot AI Jan 16, 2026

Choose a reason for hiding this comment

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

The new JupyterSubprotocol enum and JSON subprotocol support lack test coverage. Given that the repository has comprehensive test coverage for other kernel client functionality, the new subprotocol behavior (especially the JSON serialization path for Colab) should be tested to ensure correctness.

Copilot uses AI. Check for mistakes.
header=header,
metadata=metadata,
)
msg['channel'] = channel
Copy link

Copilot AI Jan 16, 2026

Choose a reason for hiding this comment

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

The 'channel' field is unconditionally added to msg for all subprotocols. This is necessary for the JSON subprotocol but may not be appropriate for the V1 subprotocol, where the channel is passed as a separate parameter to serialize_msg_to_ws_v1. Consider adding the channel field conditionally based on the subprotocol to avoid polluting the message dict unnecessarily.

Suggested change
msg['channel'] = channel
# Only include the channel in the message dict for JSON subprotocol,
# where the channel is expected to be part of the serialized message.
if self.subprotocol == JupyterSubprotocol.JSON:
msg["channel"] = channel

Copilot uses AI. Check for mistakes.
from __future__ import annotations

import datetime
import logging
Copy link

Copilot AI Jan 16, 2026

Choose a reason for hiding this comment

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

Import of 'logging' is not used.

Suggested change
import logging

Copilot uses AI. Check for mistakes.

from datetime import datetime, timedelta, timezone, tzinfo
import json
import logging
Copy link

Copilot AI Jan 16, 2026

Choose a reason for hiding this comment

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

Import of 'logging' is not used.

Suggested change
import logging

Copilot uses AI. Check for mistakes.
from __future__ import annotations


import json
Copy link

Copilot AI Jan 16, 2026

Choose a reason for hiding this comment

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

Import of 'json' is not used.

Suggested change
import json

Copilot uses AI. Check for mistakes.
@echarles echarles added the enhancement New feature or request label Jan 20, 2026
@echarles echarles changed the title BACKPORT - Changes to support talking to Colab from the JKC 🔙 Backport Support talking to Colab from the JKC Jan 20, 2026
@echarles echarles assigned echarles and unassigned eleonorecharles Jan 23, 2026
teeler and others added 2 commits January 28, 2026 21:23
Add support for listing kernels
…tocol (#3)

* Add serializers and deserializers for Jupyter's default websocket
protocol

* Adds a default serializer/deserializer
	- Logic unabashedly swiped from https://github.com/jupyterlab/jupyterlab/blob/main/packages/services/src/kernel/serialize.ts#L216
* Sets default values for the protocol as DEFAULT since it's... the
  default
* Adds simple testing for the serializers/deserializers
* Fixes minor bug with the logger being angry about multiple channels
  being defined

* didn't realize that  was a required arg for

* ugh from_bytes as well

* in tests as well

* address comments

* fix uv.lock

* fix uv.lock

---------

Co-authored-by: Drake Aiman <drakeaiman@google.com>
Copy link
Member Author

@echarles echarles left a comment

Choose a reason for hiding this comment

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

LGTM

@echarles echarles merged commit 786cdc3 into datalayer:main Feb 4, 2026
2 of 9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

🔙 Backport Support talking to Colab from the JKC

4 participants