[pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
This commit is contained in:
parent
c9ff52ba04
commit
7b5bb24900
8 changed files with 167 additions and 87 deletions
|
|
@ -51,7 +51,9 @@ def resolve_latest_tag(repo: str) -> str:
|
|||
final_url = response.geturl()
|
||||
marker = "/releases/tag/"
|
||||
if marker not in final_url:
|
||||
raise SystemExit(f"FAIL: could not resolve latest release of {repo} (landed on {final_url})")
|
||||
raise SystemExit(
|
||||
f"FAIL: could not resolve latest release of {repo} (landed on {final_url})"
|
||||
)
|
||||
return final_url.rsplit(marker, 1)[1].strip("/")
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -49,14 +49,14 @@ CURATED = [
|
|||
|
||||
|
||||
def main() -> int:
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument("--src", required=True, help="Studio 'Sloth emojis' dir")
|
||||
parser.add_argument("--dest", required=True, help="output dir (static/sloth)")
|
||||
parser = argparse.ArgumentParser(description = __doc__)
|
||||
parser.add_argument("--src", required = True, help = "Studio 'Sloth emojis' dir")
|
||||
parser.add_argument("--dest", required = True, help = "output dir (static/sloth)")
|
||||
args = parser.parse_args()
|
||||
|
||||
os.makedirs(args.dest, exist_ok=True)
|
||||
os.makedirs(args.dest, exist_ok = True)
|
||||
installed = 0
|
||||
for index, name in enumerate(CURATED, start=1):
|
||||
for index, name in enumerate(CURATED, start = 1):
|
||||
source = os.path.join(args.src, name)
|
||||
target = os.path.join(args.dest, "%02d.png" % index)
|
||||
if not os.path.isfile(source):
|
||||
|
|
|
|||
|
|
@ -38,14 +38,14 @@ def colab_cell_magic_fix(lines):
|
|||
for i, line in enumerate(lines):
|
||||
stripped = line.strip()
|
||||
if stripped == "" or stripped.startswith("#"):
|
||||
skipped.append(line) # blank or comment (incl. #@title)
|
||||
skipped.append(line) # blank or comment (incl. #@title)
|
||||
continue
|
||||
# First real line. Only act if it is a cell magic that is not yet on
|
||||
# top (i.e. something was skipped before it).
|
||||
if stripped.startswith("%%") and i > 0:
|
||||
return [line] + skipped + lines[i + 1:]
|
||||
return lines # already on top, or not a magic
|
||||
return lines # all blank/comment -> nothing to do
|
||||
return [line] + skipped + lines[i + 1 :]
|
||||
return lines # already on top, or not a magic
|
||||
return lines # all blank/comment -> nothing to do
|
||||
except Exception:
|
||||
return lines
|
||||
|
||||
|
|
@ -62,4 +62,4 @@ def register_ipython():
|
|||
ip.input_transformers_cleanup.append(colab_cell_magic_fix)
|
||||
ip._unsloth_colab_fix = True
|
||||
except Exception as e: # never break a kernel because of the helper
|
||||
print(f"[unsloth-nb] colab-compat hook skipped: {e!r}", file=sys.stderr)
|
||||
print(f"[unsloth-nb] colab-compat hook skipped: {e!r}", file = sys.stderr)
|
||||
|
|
|
|||
|
|
@ -25,7 +25,6 @@ except Exception as _e: # never break a kernel because of the helper
|
|||
# failure here never disables the transformers-sidecar hook above and vice versa.
|
||||
try:
|
||||
import unsloth_colab_compat
|
||||
|
||||
unsloth_colab_compat.register_ipython()
|
||||
except Exception as _e: # never break a kernel because of the helper
|
||||
import sys
|
||||
|
|
|
|||
|
|
@ -34,9 +34,14 @@ def _logging_enabled() -> bool:
|
|||
`[unsloth-nb] activated transformers sidecar ...` line noisy. Set
|
||||
UNSLOTH_ENABLE_LOGGING=1 to surface it (and other [unsloth-nb] diagnostics)."""
|
||||
return os.environ.get("UNSLOTH_ENABLE_LOGGING", "").strip().lower() not in (
|
||||
"", "0", "false", "no", "off",
|
||||
"",
|
||||
"0",
|
||||
"false",
|
||||
"no",
|
||||
"off",
|
||||
)
|
||||
|
||||
|
||||
# Model-name -> minimum transformers tier, ported from Studio's
|
||||
# transformers_version.py (substring match on the lowered model id). Used as a
|
||||
# fallback when a notebook does not pin transformers but names a new-family model.
|
||||
|
|
|
|||
|
|
@ -60,9 +60,9 @@ def _strip_lines(lines):
|
|||
or None if there was nothing to strip."""
|
||||
for i, line in enumerate(lines):
|
||||
if line.lstrip().lower().startswith(_INTRO_PREFIX):
|
||||
out = lines[:i] + lines[i + 1:]
|
||||
out = lines[:i] + lines[i + 1 :]
|
||||
if i < len(out) and out[i].strip() == "":
|
||||
out = out[:i] + out[i + 1:]
|
||||
out = out[:i] + out[i + 1 :]
|
||||
return out
|
||||
return None
|
||||
|
||||
|
|
@ -77,7 +77,7 @@ def _strip_intro(nb):
|
|||
return False
|
||||
src = cell.get("source")
|
||||
if isinstance(src, str):
|
||||
lines = src.splitlines(keepends=True)
|
||||
lines = src.splitlines(keepends = True)
|
||||
as_str = True
|
||||
elif isinstance(src, list):
|
||||
lines = list(src)
|
||||
|
|
@ -104,7 +104,8 @@ def _clean_widgets(nb):
|
|||
if not isinstance(outs, list):
|
||||
continue
|
||||
kept = [
|
||||
o for o in outs
|
||||
o
|
||||
for o in outs
|
||||
if not (isinstance(o, dict) and _WIDGET_VIEW_MIME in (o.get("data") or {}))
|
||||
]
|
||||
if len(kept) != len(outs):
|
||||
|
|
@ -120,7 +121,7 @@ def _clean_widgets(nb):
|
|||
def strip_notebook(path):
|
||||
"""Return True if the notebook was modified and written back."""
|
||||
try:
|
||||
with open(path, "r", encoding="utf-8") as f:
|
||||
with open(path, "r", encoding = "utf-8") as f:
|
||||
nb = json.load(f)
|
||||
except Exception:
|
||||
return False
|
||||
|
|
@ -133,8 +134,8 @@ def strip_notebook(path):
|
|||
|
||||
tmp = path + ".tmp"
|
||||
try:
|
||||
with open(tmp, "w", encoding="utf-8") as f:
|
||||
json.dump(nb, f, indent=1, ensure_ascii=False)
|
||||
with open(tmp, "w", encoding = "utf-8") as f:
|
||||
json.dump(nb, f, indent = 1, ensure_ascii = False)
|
||||
f.write("\n")
|
||||
os.replace(tmp, path)
|
||||
except Exception:
|
||||
|
|
@ -157,7 +158,7 @@ def _sha256(path):
|
|||
def migrate(state_path, dest):
|
||||
"""Strip owned+unedited notebooks listed in STATE and update their hashes."""
|
||||
try:
|
||||
with open(state_path, "r", encoding="utf-8") as f:
|
||||
with open(state_path, "r", encoding = "utf-8") as f:
|
||||
lines = f.read().splitlines()
|
||||
except OSError:
|
||||
return 0
|
||||
|
|
@ -165,7 +166,7 @@ def migrate(state_path, dest):
|
|||
out = []
|
||||
changed = 0
|
||||
for line in lines:
|
||||
parts = line.split(" ", 1) # "<sha256> <relpath>"
|
||||
parts = line.split(" ", 1) # "<sha256> <relpath>"
|
||||
if len(parts) != 2:
|
||||
out.append(line)
|
||||
continue
|
||||
|
|
@ -173,7 +174,7 @@ def migrate(state_path, dest):
|
|||
path = os.path.join(dest, rel)
|
||||
if rel.endswith(".ipynb") and os.path.isfile(path):
|
||||
try:
|
||||
if _sha256(path) == rec: # we own it and it is unedited
|
||||
if _sha256(path) == rec: # we own it and it is unedited
|
||||
if strip_notebook(path):
|
||||
rec = _sha256(path)
|
||||
changed += 1
|
||||
|
|
@ -184,7 +185,7 @@ def migrate(state_path, dest):
|
|||
if changed:
|
||||
tmp = state_path + ".tmp"
|
||||
try:
|
||||
with open(tmp, "w", encoding="utf-8") as f:
|
||||
with open(tmp, "w", encoding = "utf-8") as f:
|
||||
f.write("\n".join(out) + "\n")
|
||||
os.replace(tmp, state_path)
|
||||
except OSError:
|
||||
|
|
@ -194,10 +195,10 @@ def migrate(state_path, dest):
|
|||
|
||||
|
||||
def main(argv):
|
||||
ap = argparse.ArgumentParser(description="Strip the Colab-only intro sentence.")
|
||||
ap.add_argument("--state", help="sync state file (enables migration mode)")
|
||||
ap.add_argument("--dest", help="notebooks dir (with --state)")
|
||||
ap.add_argument("paths", nargs="*", help="notebooks to strip in place")
|
||||
ap = argparse.ArgumentParser(description = "Strip the Colab-only intro sentence.")
|
||||
ap.add_argument("--state", help = "sync state file (enables migration mode)")
|
||||
ap.add_argument("--dest", help = "notebooks dir (with --state)")
|
||||
ap.add_argument("paths", nargs = "*", help = "notebooks to strip in place")
|
||||
args = ap.parse_args(argv)
|
||||
|
||||
if args.state:
|
||||
|
|
|
|||
|
|
@ -68,11 +68,11 @@ def parse_readme(readme_path):
|
|||
|
||||
filename is the urldecoded basename under nb/ (literal parens, matching disk).
|
||||
"""
|
||||
with open(readme_path, "r", encoding="utf-8") as f:
|
||||
with open(readme_path, "r", encoding = "utf-8") as f:
|
||||
text = f.read()
|
||||
|
||||
rows = []
|
||||
seen_pairs = set() # (section, filename) already emitted
|
||||
seen_pairs = set() # (section, filename) already emitted
|
||||
section = None
|
||||
for line in text.splitlines():
|
||||
m = re.match(r"^###\s+(.*)$", line)
|
||||
|
|
@ -102,7 +102,11 @@ def _ordered_sections(rows):
|
|||
return order
|
||||
|
||||
|
||||
def build_view(dest, view, amd=False):
|
||||
def build_view(
|
||||
dest,
|
||||
view,
|
||||
amd = False,
|
||||
):
|
||||
nb_dir = os.path.join(dest, "nb")
|
||||
readme = os.path.join(dest, "README.md")
|
||||
if not os.path.isdir(nb_dir):
|
||||
|
|
@ -138,23 +142,23 @@ def build_view(dest, view, amd=False):
|
|||
|
||||
# Rebuild VIEW from scratch.
|
||||
_rmtree(view)
|
||||
os.makedirs(view, exist_ok=True)
|
||||
os.makedirs(view, exist_ok = True)
|
||||
|
||||
n_links = 0
|
||||
for i, section in enumerate(order, start=1):
|
||||
for i, section in enumerate(order, start = 1):
|
||||
folder = os.path.join(view, f"{i:02d} {section}")
|
||||
os.makedirs(folder, exist_ok=True)
|
||||
os.makedirs(folder, exist_ok = True)
|
||||
for fname in by_section[section]:
|
||||
link = os.path.join(folder, fname)
|
||||
target = os.path.join(nb_dir, fname)
|
||||
rel = os.path.relpath(target, folder) # ../../unsloth-notebooks/nb/<file>
|
||||
rel = os.path.relpath(target, folder) # ../../unsloth-notebooks/nb/<file>
|
||||
try:
|
||||
if os.path.islink(link) or os.path.exists(link):
|
||||
os.remove(link)
|
||||
os.symlink(rel, link)
|
||||
n_links += 1
|
||||
except OSError as e:
|
||||
print(f"[unsloth-nb] view: skip {fname}: {e}", file=sys.stderr)
|
||||
print(f"[unsloth-nb] view: skip {fname}: {e}", file = sys.stderr)
|
||||
return len(order), n_links
|
||||
|
||||
|
||||
|
|
@ -165,7 +169,7 @@ def _rmtree(path):
|
|||
if os.path.islink(path):
|
||||
os.remove(path)
|
||||
return
|
||||
for root, dirs, files in os.walk(path, topdown=False):
|
||||
for root, dirs, files in os.walk(path, topdown = False):
|
||||
for name in files:
|
||||
try:
|
||||
os.remove(os.path.join(root, name))
|
||||
|
|
@ -184,12 +188,16 @@ def _rmtree(path):
|
|||
|
||||
|
||||
def main(argv):
|
||||
ap = argparse.ArgumentParser(description="Build the categorized notebook view.")
|
||||
ap.add_argument("dest", help="notebooks dir (contains README.md and nb/)")
|
||||
ap.add_argument("view", nargs="?", help="output view dir (omit with --print)")
|
||||
ap.add_argument("--amd", action="store_true", help="include AMD-* notebooks")
|
||||
ap.add_argument("--print", dest="do_print", action="store_true",
|
||||
help="print section<TAB>file rows instead of building")
|
||||
ap = argparse.ArgumentParser(description = "Build the categorized notebook view.")
|
||||
ap.add_argument("dest", help = "notebooks dir (contains README.md and nb/)")
|
||||
ap.add_argument("view", nargs = "?", help = "output view dir (omit with --print)")
|
||||
ap.add_argument("--amd", action = "store_true", help = "include AMD-* notebooks")
|
||||
ap.add_argument(
|
||||
"--print",
|
||||
dest = "do_print",
|
||||
action = "store_true",
|
||||
help = "print section<TAB>file rows instead of building",
|
||||
)
|
||||
args = ap.parse_args(argv)
|
||||
|
||||
if args.do_print:
|
||||
|
|
@ -200,7 +208,7 @@ def main(argv):
|
|||
|
||||
if not args.view:
|
||||
ap.error("view dir is required unless --print is given")
|
||||
n_sections, n_links = build_view(args.dest, args.view, amd=args.amd)
|
||||
n_sections, n_links = build_view(args.dest, args.view, amd = args.amd)
|
||||
print(f"[unsloth-nb] view: {n_links} notebooks in {n_sections} folders -> {args.view}")
|
||||
return 0
|
||||
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ login branding fails CI on every device.
|
|||
Usage: python tests/validate_studio_features.py
|
||||
Exit 0 = all checks pass; non-zero = at least one failed.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import importlib
|
||||
|
|
@ -27,7 +28,11 @@ sys.path.insert(0, DOCKER)
|
|||
_failures: list[str] = []
|
||||
|
||||
|
||||
def check(name: str, cond: bool, detail: str = "") -> None:
|
||||
def check(
|
||||
name: str,
|
||||
cond: bool,
|
||||
detail: str = "",
|
||||
) -> None:
|
||||
status = "PASS" if cond else "FAIL"
|
||||
print(f" [{status}] {name}" + (f" -- {detail}" if detail and not cond else ""))
|
||||
if not cond:
|
||||
|
|
@ -40,13 +45,13 @@ def check(name: str, cond: bool, detail: str = "") -> None:
|
|||
def test_colab_compat() -> None:
|
||||
print("colab cell-magic compat (unsloth_colab_compat):")
|
||||
m = importlib.import_module("unsloth_colab_compat")
|
||||
out = m.colab_cell_magic_fix(['#@title Setup\n', '%%capture\n', '!pip install x\n'])
|
||||
check("magic hoisted above #@title", out[0] == '%%capture\n' and '#@title Setup\n' in out)
|
||||
out = m.colab_cell_magic_fix(["#@title Setup\n", "%%capture\n", "!pip install x\n"])
|
||||
check("magic hoisted above #@title", out[0] == "%%capture\n" and "#@title Setup\n" in out)
|
||||
# idempotent / already on top
|
||||
same = ['%%capture\n', 'print(1)\n']
|
||||
same = ["%%capture\n", "print(1)\n"]
|
||||
check("no-op when magic already first", m.colab_cell_magic_fix(same) == same)
|
||||
# non-magic cell untouched
|
||||
plain = ['x = 1\n', 'y = 2\n']
|
||||
plain = ["x = 1\n", "y = 2\n"]
|
||||
check("plain cell untouched", m.colab_cell_magic_fix(plain) == plain)
|
||||
|
||||
|
||||
|
|
@ -56,11 +61,16 @@ def test_colab_compat() -> None:
|
|||
def test_nb_view() -> None:
|
||||
print("notebook view (unsloth_nb_view):")
|
||||
v = importlib.import_module("unsloth_nb_view")
|
||||
check("clean_section dash/slash -> space",
|
||||
v.clean_section("### GRPO-Reinforcement/Learning Notebooks")
|
||||
== "GRPO Reinforcement Learning Notebooks",
|
||||
v.clean_section("### GRPO-Reinforcement/Learning Notebooks"))
|
||||
check("clean_section strips hashes/space", v.clean_section("## Main Notebooks ") == "Main Notebooks")
|
||||
check(
|
||||
"clean_section dash/slash -> space",
|
||||
v.clean_section("### GRPO-Reinforcement/Learning Notebooks")
|
||||
== "GRPO Reinforcement Learning Notebooks",
|
||||
v.clean_section("### GRPO-Reinforcement/Learning Notebooks"),
|
||||
)
|
||||
check(
|
||||
"clean_section strips hashes/space",
|
||||
v.clean_section("## Main Notebooks ") == "Main Notebooks",
|
||||
)
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
|
|
@ -72,27 +82,52 @@ def test_strip() -> None:
|
|||
nb = {
|
||||
"metadata": {"widgets": {"application/vnd.jupyter.widget-state+json": {"x": 1}}},
|
||||
"cells": [
|
||||
{"cell_type": "markdown",
|
||||
"source": ['To run this, press "Runtime" ... Tesla T4 Google Colab instance!\n',
|
||||
'\n', 'You will learn how to ...\n']},
|
||||
{"cell_type": "code", "source": ["print(1)\n"], "outputs": [
|
||||
{"output_type": "stream", "name": "stdout", "text": "ok\n"},
|
||||
{"output_type": "display_data",
|
||||
"data": {"application/vnd.jupyter.widget-view+json": {"model_id": "abc"},
|
||||
"text/plain": "0%| | 0/10"}},
|
||||
]},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
'To run this, press "Runtime" ... Tesla T4 Google Colab instance!\n',
|
||||
"\n",
|
||||
"You will learn how to ...\n",
|
||||
],
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": ["print(1)\n"],
|
||||
"outputs": [
|
||||
{"output_type": "stream", "name": "stdout", "text": "ok\n"},
|
||||
{
|
||||
"output_type": "display_data",
|
||||
"data": {
|
||||
"application/vnd.jupyter.widget-view+json": {"model_id": "abc"},
|
||||
"text/plain": "0%| | 0/10",
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
}
|
||||
changed1 = s._strip_intro(nb)
|
||||
changed2 = s._clean_widgets(nb)
|
||||
check("intro line stripped", changed1 and not any(
|
||||
"to run this, press" in (l.lower()) for l in nb["cells"][0]["source"]))
|
||||
check(
|
||||
"intro line stripped",
|
||||
changed1 and not any("to run this, press" in (l.lower()) for l in nb["cells"][0]["source"]),
|
||||
)
|
||||
check("intro body kept", any("You will learn" in l for l in nb["cells"][0]["source"]))
|
||||
wv = sum(1 for c in nb["cells"] for o in (c.get("outputs", []) or [])
|
||||
if "application/vnd.jupyter.widget-view+json" in (o.get("data", {}) or {}))
|
||||
wv = sum(
|
||||
1
|
||||
for c in nb["cells"]
|
||||
for o in (c.get("outputs", []) or [])
|
||||
if "application/vnd.jupyter.widget-view+json" in (o.get("data", {}) or {})
|
||||
)
|
||||
check("widget-view outputs removed", changed2 and wv == 0)
|
||||
check("non-widget outputs kept", any(
|
||||
o.get("output_type") == "stream" for c in nb["cells"] for o in (c.get("outputs", []) or [])))
|
||||
check(
|
||||
"non-widget outputs kept",
|
||||
any(
|
||||
o.get("output_type") == "stream"
|
||||
for c in nb["cells"]
|
||||
for o in (c.get("outputs", []) or [])
|
||||
),
|
||||
)
|
||||
check("metadata.widgets removed", "widgets" not in nb["metadata"])
|
||||
# idempotent
|
||||
check("strip idempotent", not s._strip_intro(nb) and not s._clean_widgets(nb))
|
||||
|
|
@ -126,21 +161,34 @@ def test_overrides() -> None:
|
|||
check("overrides.json exists", os.path.isfile(path))
|
||||
if not os.path.isfile(path):
|
||||
return
|
||||
with open(path, encoding="utf-8") as f:
|
||||
with open(path, encoding = "utf-8") as f:
|
||||
d = json.load(f) # raises -> CI fails if invalid JSON
|
||||
themes = d.get("@jupyterlab/apputils-extension:themes", {})
|
||||
check("default theme = Unsloth Dark", themes.get("theme") == "Unsloth Dark", str(themes.get("theme")))
|
||||
check(
|
||||
"default theme = Unsloth Dark",
|
||||
themes.get("theme") == "Unsloth Dark",
|
||||
str(themes.get("theme")),
|
||||
)
|
||||
check("adaptive theme on", themes.get("adaptive-theme") is True)
|
||||
check("preferred dark = Unsloth Dark", themes.get("preferred-dark-theme") == "Unsloth Dark")
|
||||
tracker = d.get("@jupyterlab/notebook-extension:tracker", {})
|
||||
check("windowingMode none", tracker.get("windowingMode") == "none", str(tracker.get("windowingMode")))
|
||||
check(
|
||||
"windowingMode none",
|
||||
tracker.get("windowingMode") == "none",
|
||||
str(tracker.get("windowingMode")),
|
||||
)
|
||||
notif = d.get("@jupyterlab/apputils-extension:notification", {})
|
||||
check("news prompt off", str(notif.get("fetchNews")) == "false" and notif.get("checkForUpdates") is False)
|
||||
check(
|
||||
"news prompt off",
|
||||
str(notif.get("fetchNews")) == "false" and notif.get("checkForUpdates") is False,
|
||||
)
|
||||
panel = d.get("@jupyterlab/notebook-extension:panel", {})
|
||||
labels = [t.get("label", "") for t in panel.get("toolbar", [])]
|
||||
check("Restart & Run All label (single >>)",
|
||||
any(l == "Restart & Run All" for l in labels) and not any(">>" in l for l in labels),
|
||||
str(labels))
|
||||
check(
|
||||
"Restart & Run All label (single >>)",
|
||||
any(l == "Restart & Run All" for l in labels) and not any(">>" in l for l in labels),
|
||||
str(labels),
|
||||
)
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
|
|
@ -151,7 +199,7 @@ def test_labext_and_branding() -> None:
|
|||
pkg = os.path.join(LABEXT, "package.json")
|
||||
check("labext package.json exists", os.path.isfile(pkg))
|
||||
if os.path.isfile(pkg):
|
||||
with open(pkg, encoding="utf-8") as f:
|
||||
with open(pkg, encoding = "utf-8") as f:
|
||||
p = json.load(f)
|
||||
check("labext name unsloth-jupyterlab", p.get("name") == "unsloth-jupyterlab")
|
||||
check("labext themePath set", bool(p.get("jupyterlab", {}).get("themePath")))
|
||||
|
|
@ -162,15 +210,20 @@ def test_labext_and_branding() -> None:
|
|||
if os.path.isdir(src_dir):
|
||||
for fn in sorted(os.listdir(src_dir)):
|
||||
if fn.endswith(".ts"):
|
||||
with open(os.path.join(src_dir, fn), encoding="utf-8") as f:
|
||||
with open(os.path.join(src_dir, fn), encoding = "utf-8") as f:
|
||||
all_src += f.read() + "\n"
|
||||
for plug in ["unsloth-jupyterlab:theme", "unsloth-jupyterlab:cell-nav",
|
||||
"unsloth-jupyterlab:logo", "unsloth-jupyterlab:colab-title",
|
||||
"unsloth-jupyterlab:output-select-all", "unsloth-jupyterlab:ui-chrome"]:
|
||||
for plug in [
|
||||
"unsloth-jupyterlab:theme",
|
||||
"unsloth-jupyterlab:cell-nav",
|
||||
"unsloth-jupyterlab:logo",
|
||||
"unsloth-jupyterlab:colab-title",
|
||||
"unsloth-jupyterlab:output-select-all",
|
||||
"unsloth-jupyterlab:ui-chrome",
|
||||
]:
|
||||
check(f"plugin present: {plug}", plug in all_src)
|
||||
# The two newest plugins are also exported from index.ts (wired in).
|
||||
index = os.path.join(src_dir, "index.ts")
|
||||
index_src = open(index, encoding="utf-8").read() if os.path.isfile(index) else ""
|
||||
index_src = open(index, encoding = "utf-8").read() if os.path.isfile(index) else ""
|
||||
check("outputSelect wired in index.ts", "outputSelectPlugin" in index_src)
|
||||
check("uiChrome wired in index.ts", "uiChromePlugin" in index_src)
|
||||
# uiChrome hides the right activity bar; CTRL+A output-select selects nodes.
|
||||
|
|
@ -178,18 +231,30 @@ def test_labext_and_branding() -> None:
|
|||
check("ctrl+A output select", "selectNodeContents" in all_src)
|
||||
# branding assets
|
||||
login = os.path.join(JUPYTER, "login.html")
|
||||
login_src = open(login, encoding="utf-8").read() if os.path.isfile(login) else ""
|
||||
login_src = open(login, encoding = "utf-8").read() if os.path.isfile(login) else ""
|
||||
check("login.html branded", "unsloth-login-card" in login_src)
|
||||
check("login.html uses sloth stickers", 'static_url("sloth/' in login_src or "static_url('sloth/" in login_src)
|
||||
check(
|
||||
"login.html uses sloth stickers",
|
||||
'static_url("sloth/' in login_src or "static_url('sloth/" in login_src,
|
||||
)
|
||||
check("favicon.ico present", os.path.isfile(os.path.join(JUPYTER, "favicon.ico")))
|
||||
check("logo.png present", os.path.isfile(os.path.join(JUPYTER, "logo.png")))
|
||||
check("sloth sticker installer present", os.path.isfile(os.path.join(JUPYTER, "install_sloth_stickers.py")))
|
||||
check(
|
||||
"sloth sticker installer present",
|
||||
os.path.isfile(os.path.join(JUPYTER, "install_sloth_stickers.py")),
|
||||
)
|
||||
|
||||
|
||||
def main() -> int:
|
||||
print("=== Unsloth Studio/notebook feature validation ===")
|
||||
for t in (test_colab_compat, test_nb_view, test_strip, test_sidecar_log_gate,
|
||||
test_overrides, test_labext_and_branding):
|
||||
for t in (
|
||||
test_colab_compat,
|
||||
test_nb_view,
|
||||
test_strip,
|
||||
test_sidecar_log_gate,
|
||||
test_overrides,
|
||||
test_labext_and_branding,
|
||||
):
|
||||
try:
|
||||
t()
|
||||
except Exception as e: # a thrown exception is a failure, not a crash
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue