diff --git a/.github/workflows/studio-backend-ci.yml b/.github/workflows/studio-backend-ci.yml index ae91e99b70..dd5efbb299 100644 --- a/.github/workflows/studio-backend-ci.yml +++ b/.github/workflows/studio-backend-ci.yml @@ -231,8 +231,6 @@ jobs: # Own step, not folded into the tests/ discovery above: pyproject's # testpaths is tests/, and this suite needs no PYTHONPATH or CUDA spoof # (it self-bootstraps sys.path and imports neither unsloth nor torch). - # Run the whole directory in one invocation; some files in it are - # order-dependent and only pass in a full-directory run. run: python -m pytest unsloth_cli/tests -q --tb=short - name: Shell installer tests diff --git a/unsloth_cli/tests/conftest.py b/unsloth_cli/tests/conftest.py new file mode 100644 index 0000000000..bb42914e69 --- /dev/null +++ b/unsloth_cli/tests/conftest.py @@ -0,0 +1,26 @@ +# SPDX-License-Identifier: AGPL-3.0-only +# Copyright 2026-present the Unsloth AI Inc. team. All rights reserved. See /studio/LICENSE.AGPL-3.0 + +"""Shared fixtures for the unsloth_cli tests.""" + +import sys +import types + +import pytest + + +@pytest.fixture +def stub_tool_policy_state(monkeypatch): + """Stub the backend's `state.tool_policy`, which run() imports in-venv. + + It lives under studio/backend, so it only imports once something has put + that directory on sys.path. Tests that reach the in-venv branch of run() + used to get that for free from whichever file ran earlier and did it as a + side effect, which made them pass only in a full-directory run. + """ + state_mod = types.ModuleType("state") + tp_mod = types.ModuleType("state.tool_policy") + tp_mod.set_tool_policy = lambda *a, **k: None + state_mod.tool_policy = tp_mod + monkeypatch.setitem(sys.modules, "state", state_mod) + monkeypatch.setitem(sys.modules, "state.tool_policy", tp_mod) diff --git a/unsloth_cli/tests/test_studio_run_parallel_flag.py b/unsloth_cli/tests/test_studio_run_parallel_flag.py index 813a251caa..9a3260d699 100644 --- a/unsloth_cli/tests/test_studio_run_parallel_flag.py +++ b/unsloth_cli/tests/test_studio_run_parallel_flag.py @@ -613,7 +613,7 @@ def test_studio_default_exposes_parallel_option(): @pytest.mark.parametrize("value", [1, 4, 8, 64]) -def test_in_venv_path_passes_parallel_to_run_server(monkeypatch, value): +def test_in_venv_path_passes_parallel_to_run_server(monkeypatch, value, stub_tool_policy_state): """In-venv path must forward --parallel to run_server(llama_parallel_slots=N), not the old hardcoded 4.""" studio_mod = _load_run_command() @@ -706,7 +706,9 @@ def test_secure_api_only_is_refused_before_any_reexec(monkeypatch, tmp_path): @pytest.mark.parametrize("extra,expected", [(["--api-only"], True), ([], False)]) -def test_in_venv_path_passes_api_only_to_run_server(monkeypatch, extra, expected): +def test_in_venv_path_passes_api_only_to_run_server( + monkeypatch, extra, expected, stub_tool_policy_state +): """In-venv path must forward --api-only to run_server(api_only=...).""" studio_mod = _load_run_command() diff --git a/unsloth_cli/tests/test_studio_secure_flag.py b/unsloth_cli/tests/test_studio_secure_flag.py index 5e60d1c40c..118f227949 100644 --- a/unsloth_cli/tests/test_studio_secure_flag.py +++ b/unsloth_cli/tests/test_studio_secure_flag.py @@ -244,7 +244,7 @@ class _RunServerCaptured(SystemExit): self.kwargs = dict(kwargs) -def test_run_in_venv_passes_secure_and_forces_host(monkeypatch, tmp_path): +def test_run_in_venv_passes_secure_and_forces_host(monkeypatch, tmp_path, stub_tool_policy_state): import types studio_mod = _studio()