Skip to content

install: fetch managed Python when distro uv.toml sets downloads=manual - #9358

Merged
oobabooga merged 5 commits into
unslothai:mainfrom
gokay-ai:cursor/fix-fedora-uv-python-downloads-manual-0c47
Aug 21, 2026
Merged

oobabooga merged 5 commits into
unslothai:mainfrom
gokay-ai:cursor/fix-fedora-uv-python-downloads-manual-0c47

Conversation

@gokay-ai

Copy link
Copy Markdown
Contributor

Summary

Studio AppImage first-run on Fedora 44 fails at “Creating virtual environment” because the distro ships /etc/uv/uv.toml with python-downloads = "manual". The installer-pinned uv still reads that file. Fedora 44’s system Python is 3.14, which the existing <3.14, !=3.13.8 bound rejects, so there is no matching interpreter and uv refuses to download one.

What changed

Added _uv_venv_requested, next to the existing _uv_venv_arm64 helper:

  1. First attempt is unchanged: uv venv --python "$(_python_request …)".
  2. If that fails and the uv error/hint says Python downloads are set to manual, run uv python install with the same request (the command Fedora already prints) and retry uv venv.
  3. Any other venv failure still propagates.
  4. Create and recreate both go through the helper, so a re-run on Fedora is covered too.
  5. A recovered fallback emits [TAURI:ERROR_CLEAR] the same way run_install_cmd / _uv_venv_arm64 already do, so Studio does not keep showing “Installation failed” after the retry succeeds.

What this does not do

  • Does not set UV_PYTHON_DOWNLOADS=automatic or UV_NO_CONFIG=1 for the Linux venv path.
  • Does not override distro uv policy globally.
  • Does not widen the <3.14 / !=3.13.8 Python bound.

Test plan

  • tests/sh/test_linux_uv_python_downloads_manual.sh (under sh and bash): clean host, Fedora-like hint, unrelated failure, uv python install failure, call-site routing, Studio ERROR_CLEAR.
  • tests/sh/test_macos_venv_python_preference.sh — arm64 helper still green.
  • tests/sh/test_install_python_guard.sh — skipped-interpreter recreate still restores on failure.

Fixes #9329

Fedora ships /etc/uv/uv.toml with python-downloads = "manual", so the
installer-pinned uv will not fetch a matching interpreter on its own.
Fedora 44 system Python is 3.14, which the existing <3.14 / !=3.13.8
bound rejects. If uv venv fails with that hint, run `uv python install`
for the same request and retry.

Fixes unslothai#9329

Co-authored-by: GokayAI <[email protected]>
Copilot AI lite review requested due to automatic review settings August 20, 2026 06:38

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates the Linux installer’s uv venv flow to recover from distros (e.g., Fedora) that ship /etc/uv/uv.toml with python-downloads = "manual", by detecting the specific uv hint and then explicitly running uv python install <request> before retrying uv venv.

Changes:

  • Add _uv_venv_requested helper to retry venv creation after installing a managed Python when uv reports downloads are set to manual.
  • Route both “create venv” and “recreate venv” call sites through the new helper (non-macOS-arm64 path).
  • Add/extend shell + Python tests to cover the Fedora hint recovery, non-hint failures, and Studio error-clear behavior.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.

File Description
install.sh Adds _uv_venv_requested and switches create/recreate venv to use it for Fedora python-downloads=manual recovery.
tests/sh/test_linux_uv_python_downloads_manual.sh New test covering Fedora-hint fallback behavior, call-site routing, and Studio ERROR_CLEAR.
tests/sh/test_install_python_guard.sh Updates helper extraction to include _uv_venv_requested.
tests/test_studio_install_workspace_guard.py Updates marker assertion to track the new helper call site.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

_raw_recreate=$(grep -c '_run_uv_venv "recreate venv"' "$INSTALL_SH" || true)
assert_eq "no leftover raw _run_uv_venv recreate venv" "0" "$_raw_recreate"

if grep -E 'UV_PYTHON_DOWNLOADS=automatic|UV_NO_CONFIG=1' "$INSTALL_SH" | grep -q '_uv_venv_requested\|python install'; then

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in f3a2e02: the assertion is grep -qE with an ERE alternation now, so it keeps checking under BSD grep.

Comment thread install.sh Outdated
Comment on lines +2928 to +2937
_uvvr_out=$(mktemp) || return 1
_uvvr_err=$(mktemp) || { rm -f "$_uvvr_out"; return 1; }
if _run_uv_venv "$_uvvr_label" "$VENV_DIR" --python "$_uvvr_req" \
>"$_uvvr_out" 2>"$_uvvr_err"; then
_uvvr_status=0
else
_uvvr_status=$?
fi
cat "$_uvvr_out"
cat "$_uvvr_err" >&2

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in f3a2e02: the capture is a tee through two FIFOs, so stdout and stderr keep flowing (and stay separate, which install.rs relies on to pair its ERROR_CLEAR twins) while uv venv runs. tests/sh/test_linux_uv_python_downloads_manual.sh asserts OUTPUT_CLEAR is visible while the venv command is still running.

@danielhanchen

Copy link
Copy Markdown
Member

Confirmed install.sh still calls _run_uv_venv directly for both create and recreate, so the manual-downloads hint is never acted on, and the retry here is the right direction. The buffering into temp files holds back the [TAURI:*] markers until venv creation ends, so could you tee the streams instead of redirecting them and keep the helper otherwise as-is?

Hold [TAURI:*] in temp files until uv venv returns, and a recovered
Fedora fallback looks idle. mkfifo + tee copies stdout/stderr as they
arrive; hint detection, uv python install, and the retry are unchanged.

Co-authored-by: GokayAI <[email protected]>
@gokay-ai

Copy link
Copy Markdown
Contributor Author

Teed the streams so [TAURI:*] markers flow live; helper otherwise unchanged.

@oobabooga

Copy link
Copy Markdown
Member

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f3a2e0213a

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread install.sh Outdated
_uvvr_req="$(_python_request "$PYTHON_VERSION")"
# Tee, don't redirect-and-replay: Studio consumes [TAURI:*] as they arrive,
# and holding them until uv venv exits makes a recovered fallback look idle.
_uvvr_dir=$(mktemp -d "${TMPDIR:-/tmp}/unsloth-uv-venv.XXXXXX") || return 1

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Register the venv capture directory for trap cleanup

When the installer receives HUP, INT, or TERM after this mktemp succeeds, _on_install_signal calls _cleanup_install_temporaries, but that cleanup does not know about _uvvr_dir; control therefore never reaches any of this helper's normal rm -rf paths. Cancelling venv creation consequently leaves an unsloth-uv-venv.* directory containing the FIFOs and captured output in the user's temporary directory, so this path should be initialized and removed by the global cleanup logic.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in e1b6394. The capture directory is _UV_VENV_CAPTURE_DIR now, initialized with the other installer temporaries before the traps are installed and removed by _cleanup_install_temporaries, so a signal during venv creation no longer leaves unsloth-uv-venv.* with its FIFOs in TMPDIR. The new test sends TERM while uv venv is running, under sh and bash, and asserts the case TMPDIR is empty afterwards; against f3a2e02 it reports the leftover directory.

clean) return 0 ;;
fedora)
if [ "$_uvvr_n" -eq 1 ]; then
echo "'"$_FEDORA_HINT"'" >&2

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve the Fedora hint literally in the test shell

When this Fedora branch runs, interpolating _FEDORA_HINT directly into the sh -c program leaves its backticks active, so the nested shell performs command substitution on uv python install >=3.13, !=3.13.8, <3.14. The range is then parsed as shell redirections: the test emits cannot open 3.14 and leaves an untracked empty =3.13, file in its working directory, while its loose assertions still report success. Quote or pass the hint as data so running this test does not execute its example command or dirty the checkout.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 65d497b. Reproduced first: the suite left an empty file named '=3.13,' in the working directory and printed 'cannot open 3.14', while the assertions still passed because the substring the helper greps for survives the substitution. The hint now reaches the nested shell through the environment, so its backticks stay data, and there is an assertion that the backticked example command arrives verbatim, which fails on f3a2e02.

@oobabooga

Copy link
Copy Markdown
Member

Pushed two follow-ups to this branch.

e1b6394 covers what the capture machinery still owed:

  • The temp directory holding the FIFOs is _UV_VENV_CAPTURE_DIR now, declared with the other installer temporaries before the traps are installed and removed by _cleanup_install_temporaries, so cancelling during venv creation no longer leaves unsloth-uv-venv.* in TMPDIR.
  • If the capture cannot be set up, the helper runs the plain uv venv instead of failing. Measured against the previous commit: mkfifo failing returned 1 with no output at all, and no tee on PATH killed the installer with SIGPIPE, both on hosts where the venv would otherwise be created. This is the same trade _uv_download_markers makes when awk is missing, and it keeps the helper from ever turning a working install into a failed one.

It also corrects the comment above the helper. An env var prefixed on one command is exactly as narrow as this fallback, so that was not the reason to avoid it. The reason that holds is python-downloads = "never": it refuses uv python install ("Python downloads are not allowed"), while UV_PYTHON_DOWNLOADS=automatic overrides it, so the explicit install is the option that leaves a distro which ruled downloads out with its answer. Checked both ways on uv 0.11.16.

65d497b is the test fix in the thread above.

Verification on fedora:44 with dnf install -y uv (uv 0.12.3) and the distro /etc/uv/uv.toml: uv venv --python '>=3.13,<3.14,!=3.13.8' fails with rc 2 and the manual-downloads hint, and the helper recovers to a Python 3.13.15 interpreter, quiet and verbose alike. tests/sh/test_linux_uv_python_downloads_manual.sh is 62/62 under bash and dash and leaves no files behind; test_install_python_guard.sh, test_macos_venv_python_preference.sh, test_macos_uv_install_name_tool_guard.sh and tests/test_studio_install_workspace_guard.py are unchanged and green.

One thing left as is: the second guard, grep -q "python-downloads", is broader than the hint it backs up, since a uv.toml parse error naming that key would also match. The cost when it misfires is one refused uv python install and the same overall failure, and it is cheap insurance if uv rewords the hint, which the first pattern matched verbatim on both 0.11.16 and 0.12.3.

@oobabooga

Copy link
Copy Markdown
Member

@codex review

1 similar comment
@oobabooga

Copy link
Copy Markdown
Member

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Swish!

Reviewed commit: 65d497b8c4

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@oobabooga

Copy link
Copy Markdown
Member

The red pre-commit.ci check does not come from this branch. ruff-format-with-kwargs rewrites six files that arrived on main: studio/backend/core/inference/llama_cpp.py, studio/backend/core/inference/llama_server_args.py, studio/backend/routes/inference.py, and the test_llama_admission_kv_budget* / test_web_page_cap_fits_window tests. Running the hook against origin/main on its own modifies exactly those six, and against main merged with this branch it is the same six again, so nothing here contributes to it. The run that passed at 11:59 predates those commits. Same shape as #9414; it needs a formatting commit on main rather than anything on this PR.

@oobabooga

Copy link
Copy Markdown
Member

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Keep it up!

Reviewed commit: 65d497b8c4

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@oobabooga

Copy link
Copy Markdown
Member

Thanks @gokay-ai. I reproduced the Fedora 44 python-downloads = "manual" failure and verified that the new venv helper installs a matching managed Python while preserving never, unrelated failures, streaming markers, and create/recreate behavior; the focused Linux and macOS installer tests passed.

@oobabooga
oobabooga merged commit 64a2982 into unslothai:main Aug 21, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] Unsloth Desktop AppImage installation fails on Fedora

5 participants