From 2bea7862ef32d8656d99e906be7efc54c968d287 Mon Sep 17 00:00:00 2001 From: Daniel Han Date: Mon, 27 Jul 2026 06:50:10 -0700 Subject: [PATCH] pip: declare click, which typer no longer pulls in (#7504) unsloth_cli/commands/start.py imports click at module scope, and unsloth_cli/__init__.py imports that module, so every unsloth command needs it. typer carried click through 0.19 and dropped it in 0.27, and the declared floor is typer>=0.12.0, so a fresh resolve gets none. The wheel still works today only because huggingface_hub requires click<9,>=8.4.2, which is luck rather than a declaration. Verified on a wheel built from a dependency list without that transitive provider: every command, including `unsloth --help`, died with ModuleNotFoundError for click. Same class as the structlog gap in #7493, so the drift test covers both now. --- pyproject.toml | 4 ++++ .../studio/install/test_studio_extra_matches_requirements.py | 5 +++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index fdbee69c58..d0b0845b93 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -55,6 +55,10 @@ dependencies = [ # Every CLI command imports studio.backend.*, which reaches structlog at # module level. The rest of the server stack lives in the studio extra. "structlog>=24.1.0", + # unsloth_cli/commands/start.py imports click, and unsloth_cli/__init__.py + # imports that, so every command needs it. typer supplied it until 0.27 + # dropped the dependency, which left this satisfied only by chance. + "click>=8.0", ] [project.scripts] diff --git a/tests/studio/install/test_studio_extra_matches_requirements.py b/tests/studio/install/test_studio_extra_matches_requirements.py index a74d52ff40..83988ce64e 100644 --- a/tests/studio/install/test_studio_extra_matches_requirements.py +++ b/tests/studio/install/test_studio_extra_matches_requirements.py @@ -17,8 +17,9 @@ REPO_ROOT = pathlib.Path(__file__).resolve().parents[3] PYPROJECT = REPO_ROOT / "pyproject.toml" STUDIO_TXT = REPO_ROOT / "studio" / "backend" / "requirements" / "studio.txt" -# Imported at module scope by the studio.backend chain every CLI command walks. -CORE_RUNTIME_PACKAGES = ("structlog",) +# Imported at module scope by the chain every CLI command walks: structlog via +# studio.backend, click via unsloth_cli/commands/start.py. +CORE_RUNTIME_PACKAGES = ("structlog", "click") def _load_pyproject() -> dict: