From a1c7b95a5aeea35336dce12a78426ec17d48c7da Mon Sep 17 00:00:00 2001 From: Daniel Han Date: Fri, 3 Apr 2026 13:50:15 +0000 Subject: [PATCH] Consolidate manifest parsing and add debug logging - Replace 8 separate Python invocations for JSON field extraction with a single Python call that outputs shell-safe eval assignments via shlex.quote. This reduces setup.sh startup overhead by ~400ms. - Add debug-level logging to exception handlers in update_check.py instead of silently swallowing errors, aiding troubleshooting when manifest fetch or critical-time comparison fails. --- studio/backend/utils/update_check.py | 8 ++++++-- studio/setup.sh | 29 ++++++++++++++++++++-------- 2 files changed, 27 insertions(+), 10 deletions(-) diff --git a/studio/backend/utils/update_check.py b/studio/backend/utils/update_check.py index b6005d5623..2a806239ae 100644 --- a/studio/backend/utils/update_check.py +++ b/studio/backend/utils/update_check.py @@ -21,10 +21,13 @@ import calendar import json import time import urllib.request +import logging from dataclasses import dataclass, field from pathlib import Path from typing import Optional +_log = logging.getLogger(__name__) + _MANIFEST_URL = ( "https://raw.githubusercontent.com/unslothai/unsloth/main/" "UNSLOTH_UPDATE_DETAILS.json" @@ -64,6 +67,7 @@ def fetch_and_cache_update_status() -> UpdateStatus: with urllib.request.urlopen(req, timeout = _FETCH_TIMEOUT) as resp: manifest = json.loads(resp.read().decode("utf-8")) except Exception: + _log.debug("manifest fetch failed", exc_info = True) return _cached_status status = UpdateStatus(manifest_fetched = True) @@ -79,11 +83,11 @@ def fetch_and_cache_update_status() -> UpdateStatus: info = json.loads(_STUDIO_INFO_PATH.read_text(encoding = "utf-8")) installed_ts = _parse_iso_utc(info.get("installed_at_utc", "")) except Exception: - pass + _log.debug("failed to read studio info", exc_info = True) if installed_ts < critical_ts: status.critical = True except Exception: - pass + _log.debug("critical time comparison failed", exc_info = True) # -- Announcement -- announcement = manifest.get("announcement") diff --git a/studio/setup.sh b/studio/setup.sh index 90a84f32cb..183d015359 100755 --- a/studio/setup.sh +++ b/studio/setup.sh @@ -44,14 +44,27 @@ MANIFEST_ANNOUNCEMENT_URL="" _fetch_manifest() { local _raw _raw=$(curl -fsSL --max-time 8 "$_MANIFEST_URL" 2>/dev/null) || return 0 - MANIFEST_UNSLOTH_SOURCE=$(printf '%s' "$_raw" | python -c "import sys,json; print(json.load(sys.stdin).get('unsloth_source',''))" 2>/dev/null || true) - MANIFEST_UNSLOTH_GITHUB_REF=$(printf '%s' "$_raw" | python -c "import sys,json; print(json.load(sys.stdin).get('unsloth_github_ref','main'))" 2>/dev/null || true) - MANIFEST_LLAMA_CPP_SOURCE=$(printf '%s' "$_raw" | python -c "import sys,json; print(json.load(sys.stdin).get('llama_cpp_source',''))" 2>/dev/null || true) - MANIFEST_LLAMA_CPP_TAG=$(printf '%s' "$_raw" | python -c "import sys,json; print(json.load(sys.stdin).get('llama_cpp_tag',''))" 2>/dev/null || true) - MANIFEST_CRITICAL_TIME=$(printf '%s' "$_raw" | python -c "import sys,json; print(json.load(sys.stdin).get('CRITICAL_TIME','') or '')" 2>/dev/null || true) - MANIFEST_ANNOUNCEMENT_MESSAGE=$(printf '%s' "$_raw" | python -c "import sys,json; a=json.load(sys.stdin).get('announcement') or {}; print(a.get('message',''))" 2>/dev/null || true) - MANIFEST_ANNOUNCEMENT_BADGE=$(printf '%s' "$_raw" | python -c "import sys,json; a=json.load(sys.stdin).get('announcement') or {}; print(a.get('badge',''))" 2>/dev/null || true) - MANIFEST_ANNOUNCEMENT_URL=$(printf '%s' "$_raw" | python -c "import sys,json; a=json.load(sys.stdin).get('announcement') or {}; print(a.get('url',''))" 2>/dev/null || true) + # Parse all manifest fields in a single Python invocation to avoid + # spawning 8 separate processes (each adds ~50ms startup overhead). + eval "$(printf '%s' "$_raw" | python -c " +import sys, json, shlex +try: + m = json.load(sys.stdin) +except Exception: + sys.exit(0) +a = m.get('announcement') or {} +for k, v in [ + ('MANIFEST_UNSLOTH_SOURCE', m.get('unsloth_source', '')), + ('MANIFEST_UNSLOTH_GITHUB_REF', m.get('unsloth_github_ref', 'main')), + ('MANIFEST_LLAMA_CPP_SOURCE', m.get('llama_cpp_source', '')), + ('MANIFEST_LLAMA_CPP_TAG', m.get('llama_cpp_tag', '')), + ('MANIFEST_CRITICAL_TIME', m.get('CRITICAL_TIME', '') or ''), + ('MANIFEST_ANNOUNCEMENT_MESSAGE', a.get('message', '')), + ('MANIFEST_ANNOUNCEMENT_BADGE', a.get('badge', '')), + ('MANIFEST_ANNOUNCEMENT_URL', a.get('url', '')), +]: + print(f'{k}={shlex.quote(str(v))}') +" 2>/dev/null)" || true substep "manifest: source=${MANIFEST_UNSLOTH_SOURCE:-pypi} llama=${MANIFEST_LLAMA_CPP_SOURCE:-default}@${MANIFEST_LLAMA_CPP_TAG:-default}" }