* Replace standalone Studio wording with Unsloth Replace the single word Studio with Unsloth wherever it is used as shorthand for Unsloth Studio in docs, CLI output, UI strings, i18n locales, workflow display names, comments and docstrings. Kept unchanged: the full name Unsloth Studio, third party product names (LM Studio, Visual Studio, Mac Studio), feature names (Recipe Studio, Fine-tuning Studio and its translations), and all identifiers such as env vars, commands, paths and filenames. * Address review feedback on the Studio wording rename Use "an" before Unsloth where the rename left the article as "a". Restore the split brand where Unsloth and Studio render as two halves of the full product name: the onboarding sidebar subtitle and the IPv6 localhost warning. Scope two messages to the full name Unsloth Studio where plain Unsloth was misleading: the AMD README bullet and the CLI studio setup error.
200 lines
6.9 KiB
Python
200 lines
6.9 KiB
Python
"""Unsloth GGUF export pins convert_hf_to_gguf.py via UNSLOTH_LLAMA_CPP_SCRIPTS_DIR, with a once-per-process warning fallback when unsloth_zoo lacks the local-script resolver."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import ast
|
|
import os
|
|
import sys
|
|
import types
|
|
from pathlib import Path
|
|
|
|
|
|
SOURCE_PATH = (
|
|
Path(__file__).resolve().parents[2] / "studio" / "backend" / "core" / "export" / "export.py"
|
|
)
|
|
SRC = SOURCE_PATH.read_text()
|
|
TREE = ast.parse(SRC)
|
|
|
|
|
|
def _module_level_assignments(tree: ast.Module):
|
|
for node in tree.body:
|
|
if isinstance(node, ast.Assign):
|
|
for target in node.targets:
|
|
if isinstance(target, ast.Name):
|
|
yield target.id, node.value
|
|
|
|
|
|
def _find_pin_try(tree: ast.AST):
|
|
for node in ast.walk(tree):
|
|
if not isinstance(node, ast.Try):
|
|
continue
|
|
for stmt in node.body:
|
|
if (
|
|
isinstance(stmt, ast.ImportFrom)
|
|
and stmt.module == "unsloth_zoo.llama_cpp"
|
|
and any(alias.name == "_resolve_local_convert_script" for alias in stmt.names)
|
|
):
|
|
return node
|
|
return None
|
|
|
|
|
|
def test_warning_flag_defined_at_module_scope():
|
|
flags = {
|
|
name: value
|
|
for name, value in _module_level_assignments(TREE)
|
|
if name == "_LLAMA_CPP_SCRIPTS_WARNING_EMITTED"
|
|
}
|
|
assert flags, "expected module-level _LLAMA_CPP_SCRIPTS_WARNING_EMITTED flag"
|
|
init = flags["_LLAMA_CPP_SCRIPTS_WARNING_EMITTED"]
|
|
assert isinstance(init, ast.Constant) and init.value is False
|
|
|
|
|
|
def test_constant_and_resolver_imported_in_same_try():
|
|
try_node = _find_pin_try(TREE)
|
|
assert try_node is not None
|
|
imported = []
|
|
for stmt in try_node.body:
|
|
if isinstance(stmt, ast.ImportFrom) and stmt.module == "unsloth_zoo.llama_cpp":
|
|
imported.extend(alias.name for alias in stmt.names)
|
|
assert "LLAMA_CPP_DEFAULT_DIR" in imported
|
|
assert "_resolve_local_convert_script" in imported
|
|
|
|
|
|
def test_setdefault_inside_try_block():
|
|
try_node = _find_pin_try(TREE)
|
|
assert try_node is not None
|
|
setdefault_calls = []
|
|
for stmt in try_node.body:
|
|
for node in ast.walk(stmt):
|
|
if (
|
|
isinstance(node, ast.Call)
|
|
and isinstance(node.func, ast.Attribute)
|
|
and node.func.attr == "setdefault"
|
|
and isinstance(node.func.value, ast.Attribute)
|
|
and node.func.value.attr == "environ"
|
|
and node.args
|
|
and isinstance(node.args[0], ast.Constant)
|
|
and node.args[0].value == "UNSLOTH_LLAMA_CPP_SCRIPTS_DIR"
|
|
):
|
|
setdefault_calls.append(node)
|
|
assert setdefault_calls
|
|
second = setdefault_calls[0].args[1]
|
|
assert isinstance(second, ast.Name) and second.id == "LLAMA_CPP_DEFAULT_DIR"
|
|
|
|
|
|
def test_warning_handler_gated_on_module_flag():
|
|
try_node = _find_pin_try(TREE)
|
|
assert try_node is not None
|
|
handlers = [
|
|
h for h in try_node.handlers if isinstance(h.type, ast.Name) and h.type.id == "ImportError"
|
|
]
|
|
assert handlers
|
|
handler = handlers[0]
|
|
flag_reads = []
|
|
flag_writes = []
|
|
warning_calls = []
|
|
for node in ast.walk(ast.Module(body = handler.body, type_ignores = [])):
|
|
if isinstance(node, ast.Name) and node.id == "_LLAMA_CPP_SCRIPTS_WARNING_EMITTED":
|
|
if isinstance(node.ctx, ast.Load):
|
|
flag_reads.append(node)
|
|
elif isinstance(node.ctx, ast.Store):
|
|
flag_writes.append(node)
|
|
elif (
|
|
isinstance(node, ast.Call)
|
|
and isinstance(node.func, ast.Attribute)
|
|
and node.func.attr == "warning"
|
|
):
|
|
warning_calls.append(node)
|
|
assert flag_reads
|
|
assert flag_writes
|
|
assert warning_calls
|
|
msg = ast.dump(warning_calls[0])
|
|
assert "UNSLOTH_LLAMA_CPP_SCRIPTS_DIR" in msg
|
|
assert "unsloth_zoo" in msg
|
|
|
|
|
|
def test_default_dir_is_string_for_setdefault_compat():
|
|
from unsloth_zoo.llama_cpp import LLAMA_CPP_DEFAULT_DIR
|
|
assert isinstance(LLAMA_CPP_DEFAULT_DIR, str)
|
|
|
|
|
|
def test_setdefault_preserves_explicit_user_override(monkeypatch):
|
|
monkeypatch.setenv("UNSLOTH_LLAMA_CPP_SCRIPTS_DIR", "/explicit/override")
|
|
from unsloth_zoo.llama_cpp import LLAMA_CPP_DEFAULT_DIR
|
|
|
|
os.environ.setdefault("UNSLOTH_LLAMA_CPP_SCRIPTS_DIR", LLAMA_CPP_DEFAULT_DIR)
|
|
assert os.environ["UNSLOTH_LLAMA_CPP_SCRIPTS_DIR"] == "/explicit/override"
|
|
|
|
|
|
def test_setdefault_assigns_default_when_unset(monkeypatch):
|
|
monkeypatch.delenv("UNSLOTH_LLAMA_CPP_SCRIPTS_DIR", raising = False)
|
|
from unsloth_zoo.llama_cpp import LLAMA_CPP_DEFAULT_DIR
|
|
|
|
os.environ.setdefault("UNSLOTH_LLAMA_CPP_SCRIPTS_DIR", LLAMA_CPP_DEFAULT_DIR)
|
|
assert os.environ["UNSLOTH_LLAMA_CPP_SCRIPTS_DIR"] == LLAMA_CPP_DEFAULT_DIR
|
|
|
|
|
|
def _simulate_pin_block(emit_records, set_value):
|
|
fake = types.ModuleType("unsloth_zoo.llama_cpp")
|
|
if set_value is not None:
|
|
fake.LLAMA_CPP_DEFAULT_DIR = set_value
|
|
sys.modules["unsloth_zoo.llama_cpp"] = fake
|
|
|
|
state = {"emitted": False}
|
|
|
|
def run_once():
|
|
try:
|
|
from unsloth_zoo.llama_cpp import (
|
|
LLAMA_CPP_DEFAULT_DIR,
|
|
_resolve_local_convert_script, # noqa: F401
|
|
)
|
|
os.environ.setdefault("UNSLOTH_LLAMA_CPP_SCRIPTS_DIR", LLAMA_CPP_DEFAULT_DIR)
|
|
except ImportError:
|
|
if not state["emitted"]:
|
|
emit_records.append("warned")
|
|
state["emitted"] = True
|
|
|
|
return run_once
|
|
|
|
|
|
def test_warning_fires_at_most_once_across_calls(monkeypatch):
|
|
monkeypatch.delenv("UNSLOTH_LLAMA_CPP_SCRIPTS_DIR", raising = False)
|
|
emits = []
|
|
runner = _simulate_pin_block(emits, set_value = "/fake/default")
|
|
runner()
|
|
runner()
|
|
runner()
|
|
assert emits == ["warned"]
|
|
|
|
|
|
def test_missing_default_dir_degrades_to_warning(monkeypatch):
|
|
monkeypatch.delenv("UNSLOTH_LLAMA_CPP_SCRIPTS_DIR", raising = False)
|
|
emits = []
|
|
runner = _simulate_pin_block(emits, set_value = None)
|
|
runner()
|
|
assert emits == ["warned"]
|
|
assert "UNSLOTH_LLAMA_CPP_SCRIPTS_DIR" not in os.environ
|
|
|
|
|
|
def test_no_warning_when_both_symbols_present(monkeypatch):
|
|
monkeypatch.delenv("UNSLOTH_LLAMA_CPP_SCRIPTS_DIR", raising = False)
|
|
fake = types.ModuleType("unsloth_zoo.llama_cpp")
|
|
fake.LLAMA_CPP_DEFAULT_DIR = "/fake/dir"
|
|
fake._resolve_local_convert_script = lambda: None
|
|
monkeypatch.setitem(sys.modules, "unsloth_zoo.llama_cpp", fake)
|
|
|
|
emits = []
|
|
state = {"emitted": False}
|
|
try:
|
|
from unsloth_zoo.llama_cpp import (
|
|
LLAMA_CPP_DEFAULT_DIR,
|
|
_resolve_local_convert_script, # noqa: F401
|
|
)
|
|
os.environ.setdefault("UNSLOTH_LLAMA_CPP_SCRIPTS_DIR", LLAMA_CPP_DEFAULT_DIR)
|
|
except ImportError:
|
|
if not state["emitted"]:
|
|
emits.append("warned")
|
|
state["emitted"] = True
|
|
|
|
assert emits == []
|
|
assert os.environ.get("UNSLOTH_LLAMA_CPP_SCRIPTS_DIR") == "/fake/dir"
|