Conversation
0311076 to
810dd58
Compare
crichalchemist
left a comment
There was a problem hiding this comment.
Thanks for this. The range looks right, but I'd suggest raising the floor from 0.8 to 0.9: "jupyter-kernel-client>=0.9,<1.0". I tested both floors today against main (e25c265).
1. With a 0.8 floor, pip users already on 0.7.2 stay broken after upgrading. In a venv with google-colab-cli==0.7.2 (so jkc 0.8.0 from PyPI), pip install --upgrade to a wheel built from this branch leaves jkc at 0.8.0. pip's default only-if-needed upgrade strategy sees >=0.8 as already satisfied. colab update runs exactly that command for pip installs (auto_update.py). With >=0.9,<1.0, the same upgrade moves to 0.15.0. (uv tool install -U upgrades all dependencies, so uv-tool installs are fixed with either floor.) So the installer matters for recovery, even though the original breakage hits every PyPI install regardless of installer: fresh uv tool install and pip install of 0.7.2 both resolve jkc 0.8.0.
2. The dev fork doesn't need the 0.8 floor. uv ignores version specifiers on dependencies overridden by [tool.uv.sources] with a git source: uv.lock records the fork with no specifier. With >=0.9,<1.0, uv lock leaves uv.lock byte-identical and uv sync --locked still installs the fork ("0.8.0").
Live colab exec on one CPU runtime (built wheel, isolated venvs, no mocks): 0.9.0 / 0.11.0 / 0.15.0 / 1.0.0 and the fork all work. PyPI 0.8.0 fails with JupyterSubprotocol (#137), and 1.0.2 fails with KernelClient (#94 / #125). So <1.0.1 would also be exact without #125. <1.0 is fine as the conservative choice.
Small nit: the inline comment says "0.9-0.15 has them" while the floor is 0.8. With a 0.9 floor the two agree.
Problem
PyPI installs of 0.7.x resolve
jupyter-kernel-client==0.8.0from datalayer, and that wheel is missing everythingruntime.pyneeds:kernel_clientconstruction fails:runtime.py:99readsjupyter_kernel_client.JupyterSubprotocol.DEFAULT—0.8.0 has no top-levelJupyterSubprotocol→AttributeErroron first execute._apply_ws_hook(runtime.py:55-66) doesfrom jupyter_kernel_client.wsclient import JupyterSubprotocol→ImportErroron 0.8.0; theexcept Exceptionat line 81 swallows it aslogging.debug, socolab_requestmessages are never intercepted.This doesn't reproduce in your dev environment because
[tool.uv.sources]points at the googlecolab fork, which carries the serializer work (Add serializers and deserializers for Jupyter's default websocket protocol, Jan 2026) — but it's versioned0.8.0, so==0.8from PyPI lands on datalayer's older0.8.0 instead. Classic dev/prod divergence.Fix
jupyter-kernel-client==0.8→>=0.8,<1.0.JupyterSubprotocol,wsclient._subprotocol,deserialize_msg_from_ws_default, plusColabKernelClient(the branchruntime.py:106was written for). Still pre-rename —KernelClientexists, so nothing else changes.0.8.0) still satisfies>=0.8, so devuv syncis untouched.Verification
On0.15.0:
hasattr(jkc, "JupyterSubprotocol")→ True; wsclient imports succeed; a syntheticcolab_requestwebsocket frame fires_apply_ws_hook's dispatcher end-to-end (hook fired: True ['colab_request']). On 0.8.0 (fresh PyPI install): both probes fail exactly as described above.Optional follow-up on your side: bump the fork's
_version.py(or re-sync it with datalayer) so the source override and what you publish stop drifting.