Skip to content

Commit 5358146

Browse files
committed
feat: WIP- zipapps GUI with uv
1 parent 510481d commit 5358146

2 files changed

Lines changed: 1182 additions & 7 deletions

File tree

zipapps/uv_download_python.py

Lines changed: 45 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import subprocess
3131
import sys
3232
from collections import OrderedDict
33+
from collections.abc import Callable
3334
from pathlib import Path
3435
from typing import Any
3536

@@ -41,6 +42,10 @@
4142
def _uv_bin(uv_path: str = "") -> list[str]:
4243
"""Resolve uv executable as a command list (safe for paths with spaces)."""
4344
if uv_path:
45+
# shlex.split treats backslashes as escapes, which breaks Windows paths.
46+
# Use shlex only for posix-style paths (forward slashes or quoted).
47+
if "\\" in uv_path and not uv_path.startswith('"'):
48+
return [uv_path]
4449
return shlex.split(uv_path)
4550
path = shutil.which("uv")
4651
if path:
@@ -290,23 +295,56 @@ def _flatten_install(target_path: Path) -> None:
290295
_cleanup_uv_artifacts(target_path)
291296

292297

293-
def install(request: str, target: str, uv_path: str = "", *, flatten: bool = False) -> Path:
298+
def install(
299+
request: str,
300+
target: str,
301+
uv_path: str = "",
302+
*,
303+
flatten: bool = False,
304+
on_output: Callable[[str], None] | None = None,
305+
) -> Path:
294306
"""Install Python via uv python install --install-dir."""
295307
target_path = Path(target).resolve()
296308
target_path.mkdir(parents=True, exist_ok=True)
297-
print(f"[INFO] Installing {request} to {target_path} ...")
309+
if on_output:
310+
on_output(f"Installing {request} to {target_path} ...")
298311
cmd = _uv_bin(uv_path) + [
299312
"python",
300313
"install",
301314
request,
302315
"--install-dir",
303316
str(target_path),
317+
"--no-bin",
304318
]
305-
result = subprocess.run(cmd) # noqa: S603
306-
if result.returncode != 0:
307-
raise RuntimeError(
308-
f"uv python install failed with return code {result.returncode}"
309-
)
319+
if on_output:
320+
proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True) # noqa: S603
321+
assert proc.stdout is not None
322+
buf = ""
323+
while True:
324+
ch = proc.stdout.read(1)
325+
if not ch:
326+
break
327+
if ch in ("\r", "\n"):
328+
line = buf.strip()
329+
if line:
330+
on_output(line)
331+
buf = ""
332+
else:
333+
buf += ch
334+
if buf.strip():
335+
on_output(buf.strip())
336+
proc.wait()
337+
if proc.returncode != 0:
338+
raise RuntimeError(
339+
f"uv python install failed with return code {proc.returncode}"
340+
)
341+
else:
342+
print(f"[INFO] Installing {request} to {target_path} ...")
343+
result = subprocess.run(cmd) # noqa: S603
344+
if result.returncode != 0:
345+
raise RuntimeError(
346+
f"uv python install failed with return code {result.returncode}"
347+
)
310348

311349
if flatten:
312350
_flatten_install(target_path)

0 commit comments

Comments
 (0)