classification
Title: Type: The activate script in Windows is not correct for venvs created in git-bash behavior Windows Python 3.9
process
Status: Resolution: open Mo, bwanamarko, paul.moore, steve.dower, tim.golden, zach.ware normal

Created on 2019-10-24 14:32 by Mo, last changed 2020-04-15 05:32 by bwanamarko.

Messages (5)
msg355333 - (view) Author: (Mo) Date: 2019-10-24 14:32
When creating a virtual environment on Windows from git-bash (using python -m venv), VIRTUAL_ENV in the activate script is set using a windows style path (C:\some\path) instead of the bash style (/c/some/path).

This means the system python and pip get used, despite the user thinking they are working in a venv after sourcing activate.

As activate is a bash script, the paths in it should always be in the bash style, regardless of platform.

This is described in a stack overflow issue here: https://stackoverflow.com/questions/57758841/windows-virtualenv-created-via-gitbash-using-system-python

I have confirmed the behaviour in 3.7.3, 3.7.4, 3.7.5 and 3.8.0.
msg355356 - (view) Author: (Mo) Date: 2019-10-25 08:18
The issue comes as a result of abspath on line 59 of venv/__init__.py:
env_dir = os.path.abspath(env_dir)

This returns a Windows-style path, and os.path.abspath returning in this way is *probably* correct, as the OS is Windows, despite trying to forget that by using bash.

It is still my view that the activate script is a bash script, and therefore should only contain paths in that style, but the simple solution to this issue is to change the double quotes around the definition of $VIRTUAL_ENV in the activate script to single quotes. It works. The output of "which python" is a bit odd, but this is clearly a quirk beyond Python's control. msg355382 - (view) Author: Steve Dower (steve.dower) * Date: 2019-10-25 20:06 I agree this would be better, though it may not be that easy to do. If you're running Windows Python from WSL, then your "bash style" path should be "/mnt/c/some/path", not "/c/some/path". So the answer isn't as simple as .replace('\\', '/'). I did some quick testing with posixpath and pathlib and neither has an obvious conversion from a Windows path to a POSIX path, though pathlib.PurePosixPath(pathlib.PureWindowsPath(p)) comes closest. Perhaps the best approach here is to improve activate to determine its path when run, like we did for activate.ps1? Then we don't need to substitute the path in at creation time. msg356146 - (view) Author: (Mo) Date: 2019-11-06 16:36 I had also tested with pathlib and posixpath and come to the same conclusion. As suggested by you, I looked into activate determining path when run. I believe this should do the trick (My bashfoo isn't strong, this is mostly from https://stackoverflow.com/a/179231): pushd . > /dev/null SCRIPT_PATH="${BASH_SOURCE[0]}"
if ([ -h "${SCRIPT_PATH}" ]); then while([ -h "${SCRIPT_PATH}" ]); do cd dirname "$SCRIPT_PATH"; SCRIPT_PATH=readlink "${SCRIPT_PATH}"; done
fi
cd dirname ${SCRIPT_PATH} > /dev/null cd .. > /dev/null SCRIPT_PATH=pwd; popd > /dev/null VIRTUAL_ENV="$SCRIPT_PATH"
msg366488 - (view) Author: Mark Mikofski (bwanamarko) Date: 2020-04-15 05:32
Would you consider just handling activate for windows directly in the lib/venv/__init__.py method "install_scripts(self, context, path)"
https://github.com/python/cpython/blob/4f98f465f14e7258c5b18a62c5aa114dbe1174d8/Lib/venv/__init__.py#L382

if not srcfile.endswith(('.exe', '.pdb')):

# handle activate for Windows (ignore WSL)
if srcfile == "activate":
# from docs: on unix drive is always empty
d, p = os.path.splitdrive(context.env_dir)
d = d.replace(':', '')
p = p.replace('\\', '/')
if d:
p = '/' + d + p
data = data.decode('utf-8')
data = data.replace('__VENV_DIR__', p)
data = data.encode('utf-8')

try:
data = data.decode('utf-8')
data = self.replace_variables(data, context)
data = data.encode('utf-8')
except UnicodeError as e:

IMHO I don't think the use of windows python in WSL is a realistic use-case, my preference would be to just make this fail. In fact I tried to use it, and I could not make it work.
1. /mnt/c/path/to/python -m venv venv
Error: [WinError 5] Access is denied: 'C:\\WINDOWS\\system32\\venv'
2. /mnt/c/path/to/python -m venv -m venv /mnt/c/some/path/to/venv
fails silently, appears to do nothing, venv is not created
3. /mnt/c/path/to/python -m venv -m venv 'C:/some/path/to/venv'
makes directories at C:\some\path\to\venv, but can't be activated in WSL, that I can figure out
source /mnt/c/some/path/to/venv/Scripts/activate
-bash: /mnt/c/some/path/to/venv/Scripts/activate: line 4: syntax error near unexpected token \$'{\r''
'bash: /mnt/c/some/path/to/venv/Scripts/activate: line 4: deactivate () {

I guess I don't really understand why it would be useful to use the windows python in WSL, and if that's the only thing holding a quick fix for this, I guess, I would prefer to just handle windows python in windows in git-bash, and ignore WSL. Would you be open to that?

If so, I'm happy to submit a PR

thanks!
History
Date User Action Args
2020-04-15 05:32:32bwanamarkosetnosy: + bwanamarko
messages: + msg366488
2019-11-06 16:36:02Mosetmessages: + msg356146
2019-10-25 20:06:48steve.dowersetmessages: + msg355382
versions: + Python 3.9, - Python 3.7, Python 3.8
2019-10-25 08:18:19Mosetmessages: + msg355356
2019-10-24 14:32:03Mocreate