Skip to content

Commit 941240c

Browse files
Merge pull request #187 from ibuildthecloud/main
bug: Fix python on windows
2 parents 2dea765 + 4337702 commit 941240c

File tree

6 files changed

+86
-51
lines changed

6 files changed

+86
-51
lines changed

pkg/env/env.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,9 @@ func AppendPath(env []string, binPath string) []string {
3939
if ok {
4040
newEnv = append(newEnv, fmt.Sprintf("PATH=%s%s%s",
4141
binPath, string(os.PathListSeparator), v))
42+
} else if v, ok := strings.CutPrefix(path, "Path="); ok {
43+
newEnv = append(newEnv, fmt.Sprintf("Path=%s%s%s",
44+
binPath, string(os.PathListSeparator), v))
4245
}
4346
}
4447
return newEnv
@@ -53,10 +56,12 @@ func Lookup(env []string, bin string) string {
5356
if !ok {
5457
continue
5558
}
59+
log.Debugf("Looking for %s in %s", bin, suffix)
5660
for _, path := range strings.Split(suffix, string(os.PathListSeparator)) {
5761
testPath := filepath.Join(path, bin)
5862

5963
if stat, err := os.Stat(testPath); err == nil && !stat.IsDir() {
64+
log.Debugf("Found %s for %s in %s", testPath, bin, suffix)
6065
return testPath
6166
}
6267

@@ -66,6 +71,7 @@ func Lookup(env []string, bin string) string {
6671
}
6772

6873
if stat, err := os.Stat(testPath + ext); err == nil && !stat.IsDir() {
74+
log.Debugf("Found %s for %s in %s", testPath+ext, bin, suffix)
6975
return testPath + ext
7076
}
7177
}

pkg/env/log.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package env
2+
3+
import "github.com/gptscript-ai/gptscript/pkg/mvl"
4+
5+
var log = mvl.Package()

pkg/repos/get.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ func (m *Manager) GetContext(ctx context.Context, tool types.Tool, cmd, env []st
111111

112112
for _, runtime := range m.runtimes {
113113
if runtime.Supports(cmd) {
114+
log.Debugf("Runtime %s supports %v", runtime.ID(), cmd)
114115
return m.setup(ctx, runtime, tool, env)
115116
}
116117
}

pkg/repos/log.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package repos
2+
3+
import "github.com/gptscript-ai/gptscript/pkg/mvl"
4+
5+
var log = mvl.Package()

pkg/repos/runtimes/env.old/env.go

Lines changed: 0 additions & 42 deletions
This file was deleted.

pkg/repos/runtimes/python/python.go

Lines changed: 69 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"encoding/json"
88
"errors"
99
"fmt"
10+
"io"
1011
"io/fs"
1112
"os"
1213
"path/filepath"
@@ -21,7 +22,7 @@ import (
2122
//go:embed python.json
2223
var releasesData []byte
2324

24-
const uvVersion = "uv==0.1.15"
25+
const uvVersion = "uv==0.1.24"
2526

2627
type Release struct {
2728
OS string `json:"os,omitempty"`
@@ -52,13 +53,65 @@ func (r *Runtime) Supports(cmd []string) bool {
5253
return runtimeEnv.Matches(cmd, "python") || runtimeEnv.Matches(cmd, "python3")
5354
}
5455

56+
func pythonCmd(base string) string {
57+
if runtime.GOOS == "windows" {
58+
return filepath.Join(base, "python.exe")
59+
}
60+
return filepath.Join(base, "python3")
61+
}
62+
63+
func pythonBin(base string) string {
64+
binDir := filepath.Join(base, "python")
65+
if runtime.GOOS != "windows" {
66+
binDir = filepath.Join(binDir, "bin")
67+
}
68+
return binDir
69+
}
70+
71+
func uvBin(binDir string) string {
72+
if runtime.GOOS == "windows" {
73+
return filepath.Join(binDir, "Scripts", "uv")
74+
}
75+
return filepath.Join(binDir, "uv")
76+
}
77+
5578
func (r *Runtime) installVenv(ctx context.Context, binDir, venvPath string) error {
5679
log.Infof("Creating virtualenv in %s", venvPath)
57-
cmd := debugcmd.New(ctx, filepath.Join(binDir, "uv"), "venv", "-p",
58-
filepath.Join(binDir, "python3"), venvPath)
80+
cmd := debugcmd.New(ctx, uvBin(binDir), "venv", "-p", pythonCmd(binDir), venvPath)
5981
return cmd.Run()
6082
}
6183

84+
func copyFile(to, from string) error {
85+
in, err := os.Open(from)
86+
if err != nil {
87+
return err
88+
}
89+
defer in.Close()
90+
91+
out, err := os.Create(to)
92+
if err != nil {
93+
_ = out.Close()
94+
return err
95+
}
96+
defer out.Close()
97+
98+
if _, err := io.Copy(out, in); err != nil {
99+
return fmt.Errorf("copying %s => %s", from, to)
100+
}
101+
102+
return nil
103+
}
104+
105+
func (r *Runtime) copyPythonForWindows(binDir string) error {
106+
for _, targetBin := range []string{"python3.exe", "python" + r.ID() + ".exe"} {
107+
err := copyFile(filepath.Join(binDir, targetBin), filepath.Join(binDir, "python.exe"))
108+
if err != nil {
109+
return err
110+
}
111+
}
112+
return nil
113+
}
114+
62115
func (r *Runtime) Setup(ctx context.Context, dataRoot, toolSource string, env []string) ([]string, error) {
63116
binPath, err := r.getRuntime(ctx, dataRoot)
64117
if err != nil {
@@ -67,6 +120,9 @@ func (r *Runtime) Setup(ctx context.Context, dataRoot, toolSource string, env []
67120

68121
venvPath := filepath.Join(dataRoot, "venv", hash.ID(binPath, toolSource))
69122
venvBinPath := filepath.Join(venvPath, "bin")
123+
if runtime.GOOS == "windows" {
124+
venvBinPath = filepath.Join(venvPath, "Scripts")
125+
}
70126

71127
// Cleanup failed runs
72128
if err := os.RemoveAll(venvPath); err != nil {
@@ -80,6 +136,12 @@ func (r *Runtime) Setup(ctx context.Context, dataRoot, toolSource string, env []
80136
newEnv := runtimeEnv.AppendPath(env, venvBinPath)
81137
newEnv = append(newEnv, "VIRTUAL_ENV="+venvPath)
82138

139+
if runtime.GOOS == "windows" {
140+
if err := r.copyPythonForWindows(venvBinPath); err != nil {
141+
return nil, err
142+
}
143+
}
144+
83145
if err := r.runPip(ctx, toolSource, binPath, append(env, newEnv...)); err != nil {
84146
return nil, err
85147
}
@@ -110,7 +172,7 @@ func (r *Runtime) runPip(ctx context.Context, toolSource, binDir string, env []s
110172
for _, req := range []string{"requirements-gptscript.txt", "requirements.txt"} {
111173
reqFile := filepath.Join(toolSource, req)
112174
if s, err := os.Stat(reqFile); err == nil && !s.IsDir() {
113-
cmd := debugcmd.New(ctx, filepath.Join(binDir, "uv"), "pip", "install", "-r", reqFile)
175+
cmd := debugcmd.New(ctx, uvBin(binDir), "pip", "install", "-r", reqFile)
114176
cmd.Env = env
115177
return cmd.Run()
116178
}
@@ -120,9 +182,7 @@ func (r *Runtime) runPip(ctx context.Context, toolSource, binDir string, env []s
120182
}
121183

122184
func (r *Runtime) setupUV(ctx context.Context, tmp string) error {
123-
cmd := debugcmd.New(ctx, filepath.Join(tmp, "python", "bin", "python3"),
124-
filepath.Join(tmp, "python", "bin", "pip"),
125-
"install", uvVersion)
185+
cmd := debugcmd.New(ctx, pythonCmd(tmp), "-m", "pip", "install", uvVersion)
126186
return cmd.Run()
127187
}
128188

@@ -133,7 +193,7 @@ func (r *Runtime) getRuntime(ctx context.Context, cwd string) (string, error) {
133193
}
134194

135195
target := filepath.Join(cwd, "python", hash.ID(url, sha, uvVersion))
136-
binDir := filepath.Join(target, "python", "bin")
196+
binDir := pythonBin(target)
137197
if _, err := os.Stat(target); err == nil {
138198
return binDir, nil
139199
} else if !errors.Is(err, fs.ErrNotExist) {
@@ -152,7 +212,7 @@ func (r *Runtime) getRuntime(ctx context.Context, cwd string) (string, error) {
152212
return "", err
153213
}
154214

155-
if err := r.setupUV(ctx, tmp); err != nil {
215+
if err := r.setupUV(ctx, pythonBin(tmp)); err != nil {
156216
return "", err
157217
}
158218

0 commit comments

Comments
 (0)