pyenv-virtualenv for Windows 1.2
A 'pyenv' plugin to manage Python virtual environments, depending on different Python versions, for various Python projects.
Loading...
Searching...
No Matches
pyenv_ori_3.1.1.bat
Go to the documentation of this file.
1@echo off
2setlocal
3chcp 65001 >nul 2>&1
4
5set "pyenv=cscript //nologo "%~dp0..\libexec\pyenv.vbs""
6
7:: if 'pyenv' called alone, then run pyenv.vbs
8if [%1]==[] (
9 %pyenv% || goto :error
10 exit /b
11)
12
13set "skip=-1"
14for /f "delims=␌" %%i in ('echo skip') do (call :incrementskip)
15if [%skip%]==[0] set "skip_arg="
16if not [%skip%]==[0] set "skip_arg=skip=%skip% "
17
18if /i [%1%2]==[version] call :check_path
19
20:: use pyenv.vbs to aid resolving absolute path of "active" version into 'bindir'
21set "bindir="
22set "extrapaths="
23for /f "%skip_arg%delims=" %%i in ('%pyenv% vname') do call :extrapath "%~dp0..\versions\%%i"
24
25:: Add %AppData% Python Scripts to %extrapaths%.
26for /F "tokens=1,2 delims=-" %%i in ('%pyenv% vname') do (
27 if /i "%%j" == "win32" (
28 for /F "tokens=1,2,3 delims=." %%a in ("%%i") do (
29 set "extrapaths=%extrapaths%%AppData%\Python\Python%%a%%b-32\Scripts;"
30 )
31 ) else (
32 for /F "tokens=1,2,3 delims=." %%a in ("%%i") do (
33 set "extrapaths=%extrapaths%%AppData%\Python\Python%%a%%b\Scripts;"
34 )
35 )
36)
37
38:: all help implemented as plugin
39if /i [%2]==[--help] goto :plugin
40if /i [%1]==[--help] (
41 call :plugin %2 %1 || goto :error
42 exit /b
43)
44if /i [%1]==[help] (
45 if [%2]==[] call :plugin help --help || goto :error
46 if not [%2]==[] call :plugin %2 --help || goto :error
47 exit /b
48)
49
50:: let pyenv.vbs handle these
51set "commands=rehash global local version vname version-name versions commands shims which whence help --help"
52for %%a in (%commands%) do (
53 if /i [%1]==[%%a] (
54 rem endlocal not really needed here since above commands do not set any variable
55 rem endlocal closed automatically with exit
56 rem no need to update PATH either
57 %pyenv% %* || goto :error
58 exit /b
59 )
60)
61
62:: jump to plugin or fall to exec
63if /i not [%1]==[exec] goto :plugin
64:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
65:exec
66
67if not exist "%bindir%" (
68 echo No global/local python version has been set yet. Please set the global/local version by typing:
69 echo pyenv global 3.7.4
70 echo pyenv local 3.7.4
71 exit /b 1
72)
73
74set cmdline=%*
75set cmdline=%cmdline:~5%
76
77:: update PATH to active version and run command
78:: endlocal needed only if cmdline sets a variable: SET FOO=BAR
79call :remove_shims_from_path
80%cmdline% || goto :error
81
82endlocal
83exit /b
84:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
85:remove_shims_from_path
86set "python_shims=%~dp0..\shims"
87call :normalizepath "%python_shims%" python_shims
88set "_path=%path%"
89set "path=%extrapaths%"
90
91:: arcane magic courtesy of StackOverflow question 5471556
92:: https://stackoverflow.com/a/7940444/381865
93setlocal DisableDelayedExpansion
94:: escape all special characters
95set "_path=%_path:"=""%"
96set "_path=%_path:^=^^%"
97set "_path=%_path:&=^&%"
98set "_path=%_path:|=^|%"
99set "_path=%_path:<=^<%"
100set "_path=%_path:>=^>%"
101set "_path=%_path:;=^;^;%"
102:: the 'missing' quotes below are intended
103set _path=%_path:""="%
104:: " => ""Q (like quote)
105set "_path=%_path:"=""Q%"
106:: ;; => "S"S (like semicolon)
107set "_path=%_path:;;="S"S%"
108set "_path=%_path:^;^;=;%"
109set "_path=%_path:""="%"
110setlocal EnableDelayedExpansion
111
112:: "Q => <empty>
113set "_path=!_path:"Q=!"
114:: "S"S => ";"
115for %%a in ("!_path:"S"S=";"!") do (
116 if "!!"=="" (
117 endlocal
118 endlocal
119 )
120 if %%a neq "" (
121 if /i not "%%~dpfa"=="%python_shims%" call :append_to_path %%~dpfa
122 )
123)
124
125exit /b
126:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
127:append_to_path
128set "path=%path%%*;"
129exit /b
130:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
131:plugin
132set "exe=%~dp0..\libexec\pyenv-%1"
133rem TODO needed?
134call :normalizepath %exe% exe
135
136if exist "%exe%.bat" (
137 set "exe=call "%exe%.bat""
138
139) else if exist "%exe%.cmd" (
140 set "exe=call "%exe%.cmd""
141
142) else if exist "%exe%.vbs" (
143 set "exe=cscript //nologo "%exe%.vbs""
144
145) else if exist "%exe%.lnk" (
146 set "exe=start '' "%exe%.bat""
147) else (
148 echo pyenv: no such command '%1'
149 exit /b 1
150)
151
152:: replace first arg with %exe%
153set cmdline=%*
154set cmdline=%cmdline:^=^^%
155set cmdline=%cmdline:!=^!%
156set "arg1=%1"
157set "len=1"
158:loop_len
159set /a len=%len%+1
160set "arg1=%arg1:~1%"
161if not [%arg1%]==[] goto :loop_len
162
163setlocal enabledelayedexpansion
164set cmdline=!exe! !cmdline:~%len%!
165:: run command (no need to update PATH for plugins)
166:: endlocal needed to ensure exit will not automatically close setlocal
167:: otherwise PYTHON_VERSION will be lost
168endlocal && endlocal && %cmdline% || goto :error
169exit /b
170:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
171:: convert path which may have relative nodes (.. or .)
172:: to its absolute value so can be used in PATH
173:normalizepath
174set "%~2=%~dpf1"
175goto :eof
176:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
177:: compute list of paths to add for all activated python versions
178:extrapath
179call :normalizepath %1 bindir
180set "extrapaths=%extrapaths%%bindir%;%bindir%\Scripts;%bindir%\bin;"
181goto :eof
182:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
183:: check pyenv python shim is first in PATH
184:check_path
185set "python_shim=%~dp0..\shims\python.bat"
186if not exist "%python_shim%" goto :eof
187call :normalizepath "%python_shim%" python_shim
188set "python_where="
189for /f "%skip_arg%delims=" %%a in ('where python') do (
190 if /i "%python_shim%"=="%%~dpfa" goto :eof
191 call :set_python_where %%~dpfa
192)
193call :bad_path "%python_where%"
194exit /b
195:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
196:: set python_where variable if empty
197:set_python_where
198if "%python_where%"=="" set "python_where=%*"
199goto :eof
200:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
201:: tell bad PATH and exit
202:bad_path
203set "bad_python=%~1"
204set "bad_dir=%~dp1"
205echo ␛[91mFATAL: Found ␛[95m%bad_python%␛[91m version before pyenv in PATH.␛[0m
206echo ␛[91mPlease remove ␛[95m%bad_dir%␛[91m from PATH for pyenv to work properly.␛[0m
207goto :eof
208:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
209:: if AutoExec/AutoRun is configured for cmd it probably ends with the `cls` command
210:: meaning there will be a Form Feed (U+000C) included in the output.
211:: so we add it as a dilimiter so that we can skip x number of lines.
212:: we find out how many to skip and pass that tot the skip option of the for loop,
213:: EXCEPT skip=0 gives errors...
214:: so we prepend every command with `echo skip` to force skip being at least 1
215:incrementskip
216set /a skip=%skip%+1
217goto :eof
218
219:error
220exit /b %errorlevel%