From 5e46e4a8d4f816812619ca67c4ff41f4aaf4006f Mon Sep 17 00:00:00 2001 From: Dan Yeaw Date: Wed, 30 Sep 2020 02:58:41 -0400 Subject: [PATCH] Fix activator path in cygwin and msys2 (#1952) Closes #1940. In cygwin and MSYS2, the path is in POSIX format. This PR converts the Windows path to POSIX format using a regex so that it is added to the bash activation script in the correct format. --- docs/changelog/1940.bugfix.rst | 1 + src/virtualenv/activation/via_template.py | 12 ++++++- .../activation/test_activation_support.py | 31 +++++++++++++++++++ 3 files changed, 43 insertions(+), 1 deletion(-) create mode 100644 docs/changelog/1940.bugfix.rst diff --git a/docs/changelog/1940.bugfix.rst b/docs/changelog/1940.bugfix.rst new file mode 100644 index 000000000..068404341 --- /dev/null +++ b/docs/changelog/1940.bugfix.rst @@ -0,0 +1 @@ +Provide correct path for bash activator in cygwin or msys2 - by :user:`danyeaw`. diff --git a/src/virtualenv/activation/via_template.py b/src/virtualenv/activation/via_template.py index 14f097973..ad91f247c 100644 --- a/src/virtualenv/activation/via_template.py +++ b/src/virtualenv/activation/via_template.py @@ -1,7 +1,9 @@ from __future__ import absolute_import, unicode_literals import os +import re import sys +import sysconfig from abc import ABCMeta, abstractmethod from six import add_metaclass @@ -31,9 +33,17 @@ def generate(self, creator): return generated def replacements(self, creator, dest_folder): + current_platform = sysconfig.get_platform() + platforms = ["mingw", "cygwin", "msys"] + if any(platform in current_platform for platform in platforms): + pattern = re.compile("^([A-Za-z]):(.*)") + match = pattern.match(str(creator.dest)) + virtual_env = "/" + match.group(1).lower() + match.group(2) + else: + virtual_env = str(creator.dest) return { "__VIRTUAL_PROMPT__": "" if self.flag_prompt is None else self.flag_prompt, - "__VIRTUAL_ENV__": ensure_text(str(creator.dest)), + "__VIRTUAL_ENV__": ensure_text(virtual_env), "__VIRTUAL_NAME__": creator.env_name, "__BIN_NAME__": ensure_text(str(creator.bin_dir.relative_to(creator.dest))), "__PATH_SEP__": ensure_text(os.pathsep), diff --git a/tests/unit/activation/test_activation_support.py b/tests/unit/activation/test_activation_support.py index d493c23ae..73424045b 100644 --- a/tests/unit/activation/test_activation_support.py +++ b/tests/unit/activation/test_activation_support.py @@ -13,6 +13,8 @@ PythonActivator, ) from virtualenv.discovery.py_info import PythonInfo +from virtualenv.info import IS_WIN +from virtualenv.util.path import Path @pytest.mark.parametrize( @@ -53,3 +55,32 @@ def test_activator_no_support_posix(mocker, activator_class): interpreter = mocker.Mock(spec=PythonInfo) interpreter.os = "posix" assert not activator.supports(interpreter) + + +class Creator: + def __init__(self): + self.dest = "C:/tools/msys64/home" + self.env_name = "venv" + self.bin_dir = Path("C:/tools/msys64/home/bin") + + +@pytest.mark.skipif(IS_WIN, reason="Github Actions ships with WSL bash") +@pytest.mark.parametrize("activator_class", [BashActivator]) +def test_cygwin_msys2_path_conversion(mocker, activator_class): + mocker.patch("sysconfig.get_platform", return_value="mingw") + activator = activator_class(Namespace(prompt=None)) + creator = Creator() + mocker.stub(creator.bin_dir.relative_to) + resource = activator.replacements(creator, "") + assert resource["__VIRTUAL_ENV__"] == "/c/tools/msys64/home" + + +@pytest.mark.skipif(IS_WIN, reason="Github Actions ships with WSL bash") +@pytest.mark.parametrize("activator_class", [BashActivator]) +def test_win_path_no_conversion(mocker, activator_class): + mocker.patch("sysconfig.get_platform", return_value="win-amd64") + activator = activator_class(Namespace(prompt=None)) + creator = Creator() + mocker.stub(creator.bin_dir.relative_to) + resource = activator.replacements(creator, "") + assert resource["__VIRTUAL_ENV__"] == "C:/tools/msys64/home"