@@ -35,12 +35,26 @@ func (p *PythonProvider) Install(ctx context.Context, tool string, installPath s
3535 return p .generic .Install (ctx , tool , installPath , artifactPath , version )
3636}
3737
38- // PostInstall creates a virtual environment.
39- func (p * PythonProvider ) PostInstall (ctx context.Context , tool string , installPath string , version string ) error {
40- pythonPath := filepath .Join (installPath , "bin" , "python3" )
38+ // getRealPythonPath resolves the actual Python binary path.
39+ // This is necessary on Windows because generic.Install creates symlinks in bin/,
40+ // and executing a symlink on Windows causes DLL resolution failures (0xc0000135)
41+ // since vcruntime140.dll is next to the real binary, not the symlink.
42+ func (p * PythonProvider ) getRealPythonPath (installPath string ) string {
4143 if runtime .GOOS == "windows" {
42- pythonPath = filepath .Join (installPath , "bin" , "python.exe" )
44+ // python-build-standalone on Windows often extracts python.exe to the root
45+ rootPy := filepath .Join (installPath , "python.exe" )
46+ if _ , err := os .Stat (rootPy ); err == nil {
47+ return rootPy
48+ }
49+ // Try bin just in case
50+ return filepath .Join (installPath , "bin" , "python.exe" )
4351 }
52+ return filepath .Join (installPath , "bin" , "python3" )
53+ }
54+
55+ // PostInstall creates a virtual environment.
56+ func (p * PythonProvider ) PostInstall (ctx context.Context , tool string , installPath string , version string ) error {
57+ pythonPath := p .getRealPythonPath (installPath )
4458
4559 venvDir := filepath .Join (installPath , "venv" )
4660 cmd := exec .CommandContext (ctx , pythonPath , "-m" , "venv" , venvDir )
@@ -57,9 +71,14 @@ func (p *PythonProvider) GenerateShims(tool string, installPath string, version
5771
5872 executables := []string {"python" , "python3" , "pip" , "pip3" }
5973 for _ , exe := range executables {
60- exePath := filepath .Join (installPath , "bin" , exe )
74+ var exePath string
75+ // Point the shim directly to the venv executables.
76+ // This natively solves the Windows symlink DLL resolution issue
77+ // and ensures the tool inherently uses its isolated environment.
6178 if runtime .GOOS == "windows" {
62- exePath += ".exe"
79+ exePath = filepath .Join (installPath , "venv" , "Scripts" , exe + ".exe" )
80+ } else {
81+ exePath = filepath .Join (installPath , "venv" , "bin" , exe )
6382 }
6483
6584 shimContent := p .generatePythonShim (exe , exePath , installPath , version )
@@ -71,10 +90,7 @@ func (p *PythonProvider) GenerateShims(tool string, installPath string, version
7190
7291// DetectVersion detects Python version.
7392func (p * PythonProvider ) DetectVersion (ctx context.Context , tool string , installPath string ) (string , error ) {
74- pythonPath := filepath .Join (installPath , "bin" , "python3" )
75- if runtime .GOOS == "windows" {
76- pythonPath = filepath .Join (installPath , "bin" , "python.exe" )
77- }
93+ pythonPath := p .getRealPythonPath (installPath )
7894
7995 cmd := exec .CommandContext (ctx , pythonPath , "--version" )
8096 output , err := cmd .Output ()
@@ -89,15 +105,21 @@ func (p *PythonProvider) DetectVersion(ctx context.Context, tool string, install
89105
90106// ListExecutables returns Python executables relative to installPath.
91107func (p * PythonProvider ) ListExecutables (tool string , installPath string , version string ) ([]string , error ) {
92- executables := []string {
93- filepath .Join ("bin" , "python" ),
94- filepath .Join ("bin" , "python3" ),
95- filepath .Join ("bin" , "pip" ),
96- filepath .Join ("bin" , "pip3" ),
97- }
108+ // Expose the venv executables so they can be discovered by generic logic if needed
109+ var executables []string
98110 if runtime .GOOS == "windows" {
99- for i := range executables {
100- executables [i ] += ".exe"
111+ executables = []string {
112+ filepath .Join ("venv" , "Scripts" , "python.exe" ),
113+ filepath .Join ("venv" , "Scripts" , "python3.exe" ),
114+ filepath .Join ("venv" , "Scripts" , "pip.exe" ),
115+ filepath .Join ("venv" , "Scripts" , "pip3.exe" ),
116+ }
117+ } else {
118+ executables = []string {
119+ filepath .Join ("venv" , "bin" , "python" ),
120+ filepath .Join ("venv" , "bin" , "python3" ),
121+ filepath .Join ("venv" , "bin" , "pip" ),
122+ filepath .Join ("venv" , "bin" , "pip3" ),
101123 }
102124 }
103125 return executables , nil
0 commit comments