ensurePythonDependenciesUV uses `uv` to create the venv and install packages.
(dir, venvPath string, w io.Writer)
| 968 | |
| 969 | // ensurePythonDependenciesUV uses `uv` to create the venv and install packages. |
| 970 | func ensurePythonDependenciesUV(dir, venvPath string, w io.Writer) error { |
| 971 | fmt.Fprintf(w, "Creating venv at %s (using uv)…\n", venvPath) |
| 972 | c := exec.Command("uv", "venv", venvPath) |
| 973 | c.Dir = dir |
| 974 | c.Stdout = w |
| 975 | c.Stderr = os.Stderr |
| 976 | if err := c.Run(); err != nil { |
| 977 | return fmt.Errorf("creating venv with uv: %w", err) |
| 978 | } |
| 979 | |
| 980 | // Prefer pyproject.toml, fall back to requirements.txt for legacy projects. |
| 981 | pyprojectFile := filepath.Join(dir, "pyproject.toml") |
| 982 | reqFile := filepath.Join(dir, "requirements.txt") |
| 983 | |
| 984 | uvEnv := append(os.Environ(), "VIRTUAL_ENV="+venvPath) |
| 985 | |
| 986 | switch { |
| 987 | case fileExists(pyprojectFile): |
| 988 | fmt.Fprintln(w, "Installing Python dependencies from pyproject.toml (using uv)…") |
| 989 | // Non-package mode projects (e.g. Poetry with package-mode = false) cannot |
| 990 | // be installed with `pip install -e .` because there is nothing to build. |
| 991 | // In that case, extract the dependency list and install packages directly. |
| 992 | if isNonPackageMode(pyprojectFile) { |
| 993 | deps := parsePyprojectDeps(pyprojectFile) |
| 994 | if len(deps) == 0 { |
| 995 | return nil // nothing to install |
| 996 | } |
| 997 | args := append([]string{"pip", "install", "-q"}, deps...) |
| 998 | c = exec.Command("uv", args...) |
| 999 | } else { |
| 1000 | c = exec.Command("uv", "pip", "install", "-e", ".", "-q") |
| 1001 | } |
| 1002 | c.Dir = dir |
| 1003 | c.Env = uvEnv |
| 1004 | c.Stdout = w |
| 1005 | c.Stderr = os.Stderr |
| 1006 | if err := c.Run(); err != nil { |
| 1007 | return fmt.Errorf("installing dependencies from pyproject.toml with uv: %w", err) |
| 1008 | } |
| 1009 | case fileExists(reqFile): |
| 1010 | fmt.Fprintln(w, "Installing Python dependencies (using uv)…") |
| 1011 | c = exec.Command("uv", "pip", "install", "-r", "requirements.txt", "-q") |
| 1012 | c.Dir = dir |
| 1013 | // Set VIRTUAL_ENV so uv pip knows which environment to install into. |
| 1014 | c.Env = uvEnv |
| 1015 | c.Stdout = w |
| 1016 | c.Stderr = os.Stderr |
| 1017 | if err := c.Run(); err != nil { |
| 1018 | return fmt.Errorf("installing dependencies with uv: %w", err) |
| 1019 | } |
| 1020 | } |
| 1021 | return nil |
| 1022 | } |
| 1023 | |
| 1024 | // ensurePythonDependenciesPip uses the standard library venv + pip workflow. |
| 1025 | func ensurePythonDependenciesPip(dir, venvPath string, w io.Writer) error { |
no test coverage detected