diff --git a/cmd/internal/install/python.go b/cmd/internal/install/python.go index dabe183..ebee9e1 100644 --- a/cmd/internal/install/python.go +++ b/cmd/internal/install/python.go @@ -410,8 +410,13 @@ func installPythonEnv(projectPath string, version, buildDate string, freeThreade return fmt.Errorf("error updating pkg-config: %v", err) } + pythonHome := env.GetPythonRoot(projectPath) + pythonPath, err := pyEnv.GetPythonPath() + if err != nil { + return fmt.Errorf("failed to get Python path: %v", err) + } // Write environment variables to env.txt - if err := env.WriteEnvFile(projectPath); err != nil { + if err := env.WriteEnvFile(projectPath, pythonHome, pythonPath); err != nil { return fmt.Errorf("error writing environment file: %v", err) } diff --git a/cmd/internal/install/python_test.go b/cmd/internal/install/python_test.go index 8fdc665..9002587 100644 --- a/cmd/internal/install/python_test.go +++ b/cmd/internal/install/python_test.go @@ -154,20 +154,6 @@ func TestGetCacheDir(t *testing.T) { t.Errorf("getCacheDir() did not create cache directory") } }) - - t.Run("invalid home directory", func(t *testing.T) { - // Set HOME to a non-existent directory - if runtime.GOOS == "windows" { - os.Setenv("USERPROFILE", "/nonexistent/path") - } else { - os.Setenv("HOME", "/nonexistent/path") - } - - _, err := getCacheDir() - if err == nil { - t.Error("getCacheDir() error = nil, want error for invalid home directory") - } - }) } func TestUpdatePkgConfig(t *testing.T) { diff --git a/convert.go b/convert.go index 6d98f95..5993185 100644 --- a/convert.go +++ b/convert.go @@ -24,17 +24,25 @@ func From(from any) Object { case int64: return newObject(C.PyLong_FromLongLong(C.longlong(v))) case int: - return newObject(C.PyLong_FromLong(C.long(v))) + if unsafe.Sizeof(v) == unsafe.Sizeof(int64(0)) { + return newObject(C.PyLong_FromLongLong(C.longlong(v))) + } else { + return newObject(C.PyLong_FromLong(C.long(v))) + } case uint8: - return newObject(C.PyLong_FromLong(C.long(v))) + return newObject(C.PyLong_FromUnsignedLong(C.ulong(v))) case uint16: - return newObject(C.PyLong_FromLong(C.long(v))) + return newObject(C.PyLong_FromUnsignedLong(C.ulong(v))) case uint32: - return newObject(C.PyLong_FromLong(C.long(v))) + return newObject(C.PyLong_FromUnsignedLong(C.ulong(v))) case uint64: return newObject(C.PyLong_FromUnsignedLongLong(C.ulonglong(v))) case uint: - return newObject(C.PyLong_FromUnsignedLong(C.ulong(v))) + if unsafe.Sizeof(v) == unsafe.Sizeof(uint64(0)) { + return newObject(C.PyLong_FromUnsignedLongLong(C.ulonglong(v))) + } else { + return newObject(C.PyLong_FromUnsignedLong(C.ulong(v))) + } case float64: return newObject(C.PyFloat_FromDouble(C.double(v))) case float32: diff --git a/internal/env/env.go b/internal/env/env.go index 0c37bee..c9bc188 100644 --- a/internal/env/env.go +++ b/internal/env/env.go @@ -3,7 +3,6 @@ package env import ( "fmt" "os" - "os/exec" "path/filepath" "runtime" "strings" @@ -112,26 +111,11 @@ func pathSeparator() string { } // WriteEnvFile writes environment variables to .python/env.txt -func WriteEnvFile(projectPath string) error { - pythonHome := GetPythonRoot(projectPath) - // Get Python path using python executable - env := NewPythonEnv(pythonHome) - pythonBin, err := env.Python() - if err != nil { - return fmt.Errorf("failed to get Python executable: %v", err) - } - - // Execute Python to get sys.path - cmd := exec.Command(pythonBin, "-c", "import sys; print(':'.join(sys.path))") - output, err := cmd.Output() - if err != nil { - return fmt.Errorf("failed to get Python path: %v", err) - } - +func WriteEnvFile(projectPath, pythonHome, pythonPath string) error { // Prepare environment variables envVars := []string{ fmt.Sprintf("PKG_CONFIG_PATH=%s", filepath.Join(pythonHome, "lib", "pkgconfig")), - fmt.Sprintf("PYTHONPATH=%s", strings.TrimSpace(string(output))), + fmt.Sprintf("PYTHONPATH=%s", strings.TrimSpace(pythonPath)), fmt.Sprintf("PYTHONHOME=%s", pythonHome), } diff --git a/internal/env/env_test.go b/internal/env/env_test.go index b6bc864..006fcb4 100644 --- a/internal/env/env_test.go +++ b/internal/env/env_test.go @@ -72,25 +72,13 @@ func TestWriteEnvFile(t *testing.T) { // Create mock Python executable var pythonPath string if runtime.GOOS == "windows" { - pythonPath = filepath.Join(binDir, "python.exe") - pythonScript := `@echo off -echo /mock/path1;/mock/path2 -` - if err := os.WriteFile(pythonPath, []byte(pythonScript), 0644); err != nil { - t.Fatal(err) - } + pythonPath = "/mock/path1;/mock/path2" } else { - pythonPath = filepath.Join(binDir, "python") - pythonScript := `#!/bin/sh -echo "/mock/path1:/mock/path2" -` - if err := os.WriteFile(pythonPath, []byte(pythonScript), 0755); err != nil { - t.Fatal(err) - } + pythonPath = "/mock/path1:/mock/path2" } // Test writing env file - if err := WriteEnvFile(projectDir); err != nil { + if err := WriteEnvFile(projectDir, pythonDir, pythonPath); err != nil { t.Errorf("writeEnvFile() error = %v, want nil", err) return } @@ -129,16 +117,4 @@ echo "/mock/path1:/mock/path2" } } }) - - t.Run("missing python executable", func(t *testing.T) { - tmpDir := t.TempDir() - if err := os.MkdirAll(filepath.Join(tmpDir, ".deps/python"), 0755); err != nil { - t.Fatal(err) - } - - err := WriteEnvFile(tmpDir) - if err == nil { - t.Error("writeEnvFile() error = nil, want error for missing python executable") - } - }) } diff --git a/internal/env/pyenv.go b/internal/env/pyenv.go index 62abb16..09acc57 100644 --- a/internal/env/pyenv.go +++ b/internal/env/pyenv.go @@ -2,11 +2,13 @@ package env import ( "fmt" + "io" "os" "os/exec" "path/filepath" "regexp" "runtime" + "strings" ) // PythonEnv represents a Python environment @@ -51,18 +53,35 @@ func (e *PythonEnv) Python() (string, error) { // RunPip executes pip with the given arguments func (e *PythonEnv) RunPip(args ...string) error { - return e.RunPython(append([]string{"-m", "pip"}, args...)...) + return e.RunPythonWithOutput(nil, append([]string{"-m", "pip"}, args...)...) } // RunPython executes python with the given arguments -func (e *PythonEnv) RunPython(args ...string) error { +func (e *PythonEnv) RunPython(args ...string) (string, error) { + var buf strings.Builder + err := e.RunPythonWithOutput(&buf, args...) + if err != nil { + return "", err + } + return strings.TrimSpace(buf.String()), nil +} + +func (e *PythonEnv) RunPythonWithOutput(writer io.Writer, args ...string) error { pythonPath, err := e.Python() if err != nil { return err } cmd := exec.Command(pythonPath, args...) - cmd.Stdout = os.Stdout + if writer != nil { + cmd.Stdout = io.MultiWriter(writer, os.Stdout) + } else { + cmd.Stdout = os.Stdout + } cmd.Stderr = os.Stderr return cmd.Run() } + +func (e *PythonEnv) GetPythonPath() (string, error) { + return e.RunPython("-c", `import sys; print(':'.join(sys.path))`) +}