unsloth/studio/backend
Daniel Han f297593a7c
Studio: keep training from failing when a namespace-package shadows unsloth (#6269)
* Studio: guard the training import against a namespace-package shadow of unsloth

A directory named unsloth without an __init__.py on sys.path (a stray checkout,
a partial clone, or a polluted PYTHONPATH) makes the path finder return a
namespace package, so the worker's 'from unsloth import FastLanguageModel' fails
with 'cannot import name ... (unknown location)'. A normal site-packages install
always wins this race, so only source/editable installs are exposed. Before the
import, drop the offending sys.path entries, bind the real packages, then
restore sys.path so other modules on those entries keep importing. It is a
no-op when unsloth already resolves to a real package.

* Studio: import unsloth before unsloth_zoo in the namespace-shadow guard

_ensure_real_packages imported the requested names in argument order, so a
unsloth_zoo namespace shadow made it import unsloth_zoo directly before
unsloth. That skips unsloth.__init__ -> _gpu_init, which runs its ROCm and
Windows bitsandbytes fixes before its own import unsloth_zoo, so the recovery
path could import zoo with those guards skipped and fail on the ROCm/Windows
cases those fixes handle.

Import parent-first via reversed(names) so unsloth is imported first and pulls
in the real unsloth_zoo after _gpu_init has run; the later cached import is a
no-op. This also covers the case where only unsloth_zoo is shadowed: the bad
sys.path entry is still dropped and unsloth owns the zoo import. Detection,
sys.path pruning, shadow-cache clearing, and restoration are unchanged.

Add tests/test_namespace_shadow_guard_pr6269.py: CPU-only subprocess scenarios
(only zoo shadowed, both shadowed, only unsloth shadowed, healthy no-op, real
package absent, multiple shadow entries) that assert unsloth imports before
unsloth_zoo and that sys.path is restored.

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

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

* Studio: restore sys.path even if invalidate_caches fails in the shadow guard

Move importlib.invalidate_caches() inside the try/finally so a failure there
still restores sys.path, and tighten the import-order comment. Add a test that
forces invalidate_caches to raise and asserts sys.path is restored.

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2026-06-15 06:06:48 -07:00
..
assets Studio: bundle Gemma 4 chat templates (E2B/E4B + larger) and auto-apply to unsloth/gemma-4-*-GGUF (#6245) 2026-06-12 05:49:39 -07:00
auth Studio: add --secure Cloudflare-only mode and revamp API usage examples (#6300) 2026-06-15 04:18:15 -07:00
core Studio: keep training from failing when a namespace-package shadows unsloth (#6269) 2026-06-15 06:06:48 -07:00
hub Studio: fix Downloaded model list disappearing and order it by last download (#6247) 2026-06-12 05:27:34 -07:00
loggers Reduce and tighten code comments and docstrings repo-wide (#6095) 2026-06-08 23:09:51 -07:00
models Studio: Bypass Permissions (skip confirmation, disable tool sandbox) (#5895) 2026-06-15 04:04:22 -07:00
plugins Reduce and tighten code comments and docstrings repo-wide (#6095) 2026-06-08 23:09:51 -07:00
requirements feat(studio): implement S3 dataset loading (completes #5951) (#6222) 2026-06-12 14:52:04 +02:00
routes Studio: coalesce orphaned GGUF user turns so strict chat templates stay alternating (#5980) 2026-06-15 04:56:11 -07:00
state Studio: Add inline confirmation (Allow/Always allow/Deny) for tool calls (#5869) 2026-06-12 10:55:26 +02:00
storage Studio: project sources backed by RAG (#6205) 2026-06-12 15:42:51 +02:00
tests Studio: keep training from failing when a namespace-package shadows unsloth (#6269) 2026-06-15 06:06:48 -07:00
utils Studio: show llama.cpp version and GPU specs in the About panel (#6261) 2026-06-15 15:25:08 +03:00
__init__.py Final cleanup 2026-03-12 18:28:04 +00:00
_platform_compat.py Reduce and tighten code comments and docstrings repo-wide (#6095) 2026-06-08 23:09:51 -07:00
cloudflare_tunnel.py Studio: only advertise a Cloudflare tunnel once it actually serves (#6264) 2026-06-12 14:36:35 -03:00
colab.py Reduce and tighten code comments and docstrings repo-wide (#6095) 2026-06-08 23:09:51 -07:00
main.py Studio: show llama.cpp version and GPU specs in the About panel (#6261) 2026-06-15 15:25:08 +03:00
run.py Studio: add --secure Cloudflare-only mode and revamp API usage examples (#6300) 2026-06-15 04:18:15 -07:00
startup_banner.py Studio: enable stdio MCP servers on a loopback bind (#6295) 2026-06-15 03:02:32 +01:00