from __future__ import annotations
import json
import platform
from dataclasses import dataclass
from importlib import resources
from ._runtime import EXTRAS, TRACKED, installed_version, is_colab
[docs]
def tested_runtime() -> dict:
"""The Colab runtime this release was tested against (generated by CI)."""
text = resources.files("colabutilscs4337").joinpath("_tested.json").read_text()
return json.loads(text)
def public_version(version: str | None) -> str | None:
"""Drop the local build tag (``2.11.0+cu130`` -> ``2.11.0``) so CPU/GPU builds match."""
return version.split("+", 1)[0] if version else version
[docs]
@dataclass(frozen=True)
class Row:
package: str
source: str
installed: str | None
tested: str | None
status: str
def _status(installed: str | None, tested: str | None) -> str:
if installed is None:
return "missing"
if tested is None:
return "ok"
return "ok" if public_version(installed) == public_version(tested) else "different"
[docs]
def check(verbose: bool = True) -> list[Row]:
"""Compare installed versions with the Colab runtime this package was tested on.
Only warns; never raises. ``different`` usually means Colab updated its runtime
since this release, or the notebook is pinned to an older runtime version.
"""
tested = tested_runtime()
tested_pkgs = tested.get("packages", {})
rows = []
for dist in TRACKED:
installed = installed_version(dist)
rows.append(
Row(
dist,
"provided by Colab",
installed,
tested_pkgs.get(dist),
_status(installed, tested_pkgs.get(dist)),
)
)
for dist in EXTRAS:
installed = installed_version(dist)
source = "provided by Colab" if dist in tested_pkgs else "installed by colabutilscs4337"
status = "ok" if installed else "missing"
rows.append(Row(dist, source, installed, tested_pkgs.get(dist), status))
if verbose:
_print(rows, tested)
return rows
def _print(rows: list[Row], tested: dict) -> None:
py_tested = tested.get("python")
py_now = platform.python_version()
print(
f"Runtime: {'Google Colab' if is_colab() else 'not Colab'}, Python {py_now} "
f"(tested: {py_tested}, Colab {tested.get('runtime', '?')} runtime synced "
f"{tested.get('synced_at', '?')})"
)
header = ("package", "source", "installed", "tested", "status")
table = [header] + [
(r.package, r.source, r.installed or "-", r.tested or "-", r.status) for r in rows
]
widths = [max(len(str(row[i])) for row in table) for i in range(len(header))]
for row in table:
print(" ".join(str(cell).ljust(w) for cell, w in zip(row, widths, strict=True)))
if py_tested and py_now.rsplit(".", 1)[0] != py_tested.rsplit(".", 1)[0]:
print(f"Warning: Python {py_now} differs from the tested Python {py_tested}.")
if any(r.status == "different" for r in rows):
print(
"Warning: some versions differ from the tested Colab runtime. Things usually still "
"work; if something breaks, run `%pip install -U colabutilscs4337` and restart."
)
missing_extras = [r.package for r in rows if r.status == "missing" and r.package in EXTRAS]
if missing_extras:
print(
f"Optional tools not installed: {', '.join(missing_extras)}. "
"Run `cu.install('all')` to add them."
)