unsloth/tests/python
Tai An 6ea2b91d04
fix(studio/install): keep the rollback reference when a venv move stops partway (#7810) (#7823)
* fix(studio/install): keep the rollback reference when a venv move stops partway (#7810)

Start-StudioVenvRollback moves the existing environment aside with a single
Move-Item and treats any failure as "the original is still in place". On
Windows that is not the shape the failure takes: an open handle inside the
tree -- a running Studio backend holds its own unsloth.exe there -- fails the
rename *after* it has already walked part of it, so the entries handled
before the locked one sit at the rollback path while the rest stay behind.

Both paths then exist, and the catch tests only the source, so it scores the
split tree as an untouched original, clears StudioVenvRollbackDir and drops
the sole record of where the other half went. The reporter was left with a
unsloth_studio\ holding 7 Scripts entries and no python.exe, an intact venv
under unsloth_studio.rollback.<stamp>.<pid>\, and no output naming either.
Retries cannot recover: the create branch keys off python.exe, and uv refuses
to build a venv over the directory the stranded files still occupy.

Clear the rollback state only when the destination is genuinely absent. When
both paths exist the move is partial, so keep it active -- the existing
finally-block Restore-StudioVenvRollback then reverses it -- and print both
locations plus the "close Unsloth Studio" hint the launcher-shim path at
install.ps1:3078 already gives for the same underlying cause.

install.sh is unaffected: POSIX rename ignores open descriptors and both
paths are siblings under , so that move really is atomic.

Regression test extracts the function from install.ps1 and runs it under real
PowerShell with Move-Item stubbed to fail after creating the destination. On
current main the partial case reports active=False with an empty rollback dir
-- the stranding itself; the clean-failure case is asserted alongside it so
the untouched-original path keeps clearing state as before.

Signed-off-by: Tai An <antai12232931@outlook.com>

* fix(studio/install): merge a split venv back instead of clearing the target

Keeping the rollback active after a partway move sent the failure path into
Restore-StudioVenvRollback, which removes $target before moving $backup back.
In the split case $target is not an incomplete *new* environment -- it holds the
half of the previous one the move never reached -- so that removal deleted files
present nowhere else and restored a corrupted venv.

Flag the split and give restoration a merge path: move each entry of the backup
into the target without overwriting, recursing where the move stopped inside a
subtree, and only drop the backup once it is empty. Anything ambiguous is left
in place and both locations are named.

Regression test pins the file that never moved to surviving restoration.

* Installer: fix split-move merge nesting siblings and walking through junctions

Two problems in Merge-StudioVenvRollbackTree, both only reachable once a partway
move leaves the venv split.

Sibling nesting. The per-entry variable was named $destination, and PowerShell
variable names are case-insensitive, so it reassigned the $Destination parameter.
Only the first entry at a level landed correctly; every later sibling was joined
onto the previous one's path, so a restored venv came back with pyvenv.cfg inside
Lib. Renamed to $entryTarget.

Junction traversal. Recursion keyed on "directory on both sides", which a junction
or directory symlink satisfies. If the half left behind holds the link, venv files
move through it and land outside $StudioHome. If the moved half holds it, the
recursion enumerates the link target and pulls those files into the venv, emptying
a directory that was never part of the environment. Either way the link is replaced
by a real directory, which the whole-tree Move-Item this path replaced never did.
Now checks both sides for a reparse point and falls through to keep-both-copies.

Attributes are read via Get-Item on both sides, since Get-ChildItem has reported
them inconsistently.

Tests cover sibling placement and both link directions. The link test uses a
junction on Windows so it does not need SeCreateSymbolicLinkPrivilege.

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

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

---------

Signed-off-by: Tai An <antai12232931@outlook.com>
Co-authored-by: danielhanchen <danielhanchen@gmail.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2026-08-06 02:09:52 -07:00
..
__init__.py Consolidate dual venvs and separate install from update (#4530) 2026-03-25 05:24:21 -07:00
conftest.py Formatting: ruff line-length 100, kwarg-spacing passes, drop blank after short local imports (#6079) 2026-06-08 04:24:13 -07:00
test_bitsandbytes_kernel_readiness.py Anchor the bnb bind assertion on the symbol, not the module alias (#7590) 2026-07-28 21:35:04 -07:00
test_change_system_message.py Escape the system message spliced into predefined chat templates (#7746) 2026-08-02 07:18:09 -07:00
test_conftest_bitsandbytes_preimport.py Tests: import bitsandbytes before the GPU-free harness spoofs CUDA (#7582) 2026-07-28 18:52:25 -07:00
test_construct_chat_template_validation.py Escape caller template text spliced into Jinja string literals (#7731) 2026-08-02 05:32:25 -07:00
test_cpo_processor_text_tokenizer.py tests: read checked-in files as UTF-8 instead of the platform default (#7438) 2026-07-26 23:31:56 -07:00
test_cross_platform_parity.py Installer: select CUDA wheels that cover the host's GPUs (#7814) 2026-08-04 06:55:29 -07:00
test_dpo_vision_processor_passthrough.py tests: read checked-in files as UTF-8 instead of the platform default (#7438) 2026-07-26 23:31:56 -07:00
test_e2e_no_torch_sandbox.py Fix Windows no-torch setup (#7511) 2026-07-28 05:54:25 -07:00
test_fast_language_model_text_only.py tests: read checked-in files as UTF-8 instead of the platform default (#7438) 2026-07-26 23:31:56 -07:00
test_fast_model_config_passthrough.py tests: read checked-in files as UTF-8 instead of the platform default (#7438) 2026-07-26 23:31:56 -07:00
test_fast_sentence_transformer_embedding_parity.py Fix FastSentenceTransformer Qwen embedding preprocessing (#6939) 2026-07-09 01:46:22 -07:00
test_fast_sentence_transformer_redirect_lifecycle.py Reduce and tighten comments and docstrings across the test suite (#6429) 2026-06-18 01:07:09 -07:00
test_flash_attn_install_python_stack.py Studio: fix flash-attn and torchao install on Blackwell (sm_100+) GPUs (Closes #6961) (#6970) 2026-07-08 06:38:10 -07:00
test_get_chat_template_escaping.py Escape the system message spliced into predefined chat templates (#7746) 2026-08-02 07:18:09 -07:00
test_get_lora_parameters_bias_fp8_block_size.py Propagate fp8 block_size before the early return in get_lora_parameters_bias (#7189) 2026-07-17 16:30:45 -07:00
test_get_lora_parameters_fp8_block_size.py Propagate fp8 block_size before the early return in get_lora_parameters_bias (#7189) 2026-07-17 16:30:45 -07:00
test_gpu_init_ldconfig_guard.py tests: read checked-in files as UTF-8 instead of the platform default (#7438) 2026-07-26 23:31:56 -07:00
test_grpo_ddp_model_config.py tests: read checked-in files as UTF-8 instead of the platform default (#7438) 2026-07-26 23:31:56 -07:00
test_import_without_bitsandbytes.py Keep import unsloth working when bitsandbytes is absent (#7502) 2026-07-28 08:03:54 -07:00
test_install_python_stack.py install: let UNSLOTH_TORCH_INDEX_FAMILY / _URL override CUDA wheel detection (#6692) 2026-07-20 00:58:52 -07:00
test_install_uv_override_space.py Installer: make UV_OVERRIDE space-safe on Apple Silicon (#6503) (#6639) 2026-06-24 17:34:18 -07:00
test_mlx_public_trainer_api.py Bound dataset_num_proc by memory, and stop treating 1 as "no multiprocessing" (#7831) 2026-08-05 05:31:27 -07:00
test_no_torch_filtering.py Fix Windows no-torch setup (#7511) 2026-07-28 05:54:25 -07:00
test_orpo_processor_text_tokenizer.py tests: read checked-in files as UTF-8 instead of the platform default (#7438) 2026-07-26 23:31:56 -07:00
test_pad_token_fix.py tests: read checked-in files as UTF-8 instead of the platform default (#7438) 2026-07-26 23:31:56 -07:00
test_patch_trl_rl_trainers_defensive.py Reduce and tighten comments and docstrings across the test suite (#6429) 2026-06-18 01:07:09 -07:00
test_remove_special_tokens_no_bos.py fix: guard remove_special_tokens against tokenizers without a BOS token (#7048) 2026-07-10 14:55:11 -03:00
test_revision_forwarding.py Forward revision to the config, weight and tokenizer loads (#4222) 2026-08-02 22:35:19 -07:00
test_studio_import_no_torch.py tests: read checked-in files as UTF-8 instead of the platform default (#7438) 2026-07-26 23:31:56 -07:00
test_to_sharegpt_optional_none.py Fix to_sharegpt optional block rendering "None" for missing extra columns (#6827) 2026-07-08 17:57:41 -03:00
test_tokenizers_and_torch_constraint.py Add Intel Arc GPU detection and XPU PyTorch install to Windows installer (#7706) 2026-08-04 03:03:10 -07:00
test_torchcodec_torch_compat.py Gate the torchcodec audio extras to platforms that have a wheel (#7587) 2026-07-28 20:56:11 -07:00
test_unsloth_run_tool_policy_resolver.py Keep server-side tools enabled under --secure (#6403) 2026-06-18 05:52:40 -07:00
test_v100_fullft_precision.py Export ACCELERATE_MIXED_PRECISION when bf16/fp16 is set explicitly (fixes #4891) (#7534) 2026-07-29 06:39:18 -07:00
test_vision_lora_targeting.py tests: read checked-in files as UTF-8 instead of the platform default (#7438) 2026-07-26 23:31:56 -07:00
test_windows_arm64_python_choice.py Windows: unblock the consumer install on clean and no-winget machines (#7549) 2026-07-28 22:24:40 -07:00
test_windows_git_gate.py Windows: do not abort setup on an unreadable llama.cpp install (#7735) 2026-08-02 07:25:39 -07:00
test_windows_no_torch_setup.py Fix Windows no-torch setup (#7511) 2026-07-28 05:54:25 -07:00
test_windows_python_313_8_screen.py Ask uv for a Python that can import torch, and skip the one that cannot (#7830) 2026-08-05 03:03:39 -07:00
test_windows_python_venv_hardening.py fix(studio/install): keep the rollback reference when a venv move stops partway (#7810) (#7823) 2026-08-06 02:09:52 -07:00
test_windows_vcredist_download_tls.py Windows: unblock the consumer install on clean and no-winget machines (#7549) 2026-07-28 22:24:40 -07:00