unsloth/tests/studio/test_cli_repo_variant.py
Daniel Han a6dc10dad2
Reduce and tighten comments and docstrings across the test suite (#6429)
* Reduce and tighten comments and docstrings in tests

Shorten verbose comments and docstrings across the test suite without
changing any test logic. Remove narration that restates the next line,
collapse long module and test docstrings to a single line, and drop banner
separators. Keep regression context (issue and PR references, run ids),
skip reasons, mocking and timing rationale, license headers, lint and type
directives, and commented-out code.

Comments and docstrings only: an AST signature check confirms no code,
assertions, or string literals changed, and the suite byte-compiles cleanly.

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2026-06-18 01:07:09 -07:00

131 lines
3.8 KiB
Python

"""Tests for the ``repo:variant`` shorthand parser used by ``unsloth studio run``.
Loads studio.py via importlib with a minimal typer stub to avoid importing the unsloth training stack.
"""
from __future__ import annotations
import importlib.util
import sys
import types
from pathlib import Path
import pytest
def _load_split_repo_variant():
"""Load ``_split_repo_variant`` from studio.py with typer stubbed (discards decorator calls)."""
if "typer" not in sys.modules:
typer_stub = types.ModuleType("typer")
class _Typer:
def __init__(self, **kwargs):
pass
def callback(self, *args, **kwargs):
return lambda fn: fn
def command(self, *args, **kwargs):
return lambda fn: fn
typer_stub.Typer = _Typer
typer_stub.Option = lambda *args, **kwargs: (args[0] if args else None)
typer_stub.Context = type("Context", (), {})
typer_stub.Exit = type("Exit", (Exception,), {})
typer_stub.echo = lambda *args, **kwargs: None
sys.modules["typer"] = typer_stub
studio_py = Path(__file__).resolve().parents[2] / "unsloth_cli" / "commands" / "studio.py"
spec = importlib.util.spec_from_file_location("_studio_for_repo_variant_test", studio_py)
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
return module._split_repo_variant
_split = _load_split_repo_variant()
# ── HF-style repo:variant inputs -------------------------------------
@pytest.mark.parametrize(
"model_arg, expected",
[
(
"unsloth/gpt-oss-20b-GGUF:UD-Q4_K_XL",
("unsloth/gpt-oss-20b-GGUF", "UD-Q4_K_XL"),
),
("unsloth/gpt-oss-120b-GGUF:Q4_K_XL", ("unsloth/gpt-oss-120b-GGUF", "Q4_K_XL")),
("unsloth/Qwen3-0.6B-GGUF:Q4_K_M", ("unsloth/Qwen3-0.6B-GGUF", "Q4_K_M")),
# Variants commonly contain dashes, dots, and underscores.
("org/repo:UD-Q5_K_M", ("org/repo", "UD-Q5_K_M")),
("org/repo:F16", ("org/repo", "F16")),
],
)
def test_repo_variant_split(model_arg, expected):
assert _split(model_arg) == expected
# ── No variant suffix ------------------------------------------------
@pytest.mark.parametrize(
"model_arg",
[
"unsloth/gpt-oss-20b-GGUF",
"unsloth/Qwen3-0.6B-GGUF",
"shorthand-no-org-no-colon",
],
)
def test_no_colon_returns_none_variant(model_arg):
repo, variant = _split(model_arg)
assert repo == model_arg
assert variant is None
# ── Local paths must NOT be split ------------------------------------
@pytest.mark.parametrize(
"local_path",
[
"/abs/path/to/model.gguf",
"/abs/path:with-colon-in-name",
"./relative/model",
"../parent/model",
"~/home/model",
".",
"C:\\Users\\me\\model.gguf",
"C:/Users/me/model.gguf",
"D:/data/model:Q4", # Windows drive + colon-suffixed filename: drive wins
],
)
def test_local_path_passthrough(local_path):
repo, variant = _split(local_path)
assert repo == local_path
assert variant is None
# ── Edge cases -------------------------------------------------------
def test_empty_string():
assert _split("") == ("", None)
def test_trailing_colon_no_variant():
# "org/repo:" has no quant label; pass through unchanged so backend validation gives a clearer error.
repo, variant = _split("org/repo:")
assert repo == "org/repo:"
assert variant is None
def test_slash_in_variant_disqualifies_split():
# "foo:bar/baz" suffix has a slash, so it's not a quant label; treat as opaque.
repo, variant = _split("foo:bar/baz")
assert repo == "foo:bar/baz"
assert variant is None
def test_whitespace_stripped():
assert _split(" org/repo:Q4 ") == ("org/repo", "Q4")