diff --git a/news/fix-virtualenv-quoting.rst b/news/fix-virtualenv-quoting.rst new file mode 100644 index 000000000..3b7a898a7 --- /dev/null +++ b/news/fix-virtualenv-quoting.rst @@ -0,0 +1,23 @@ +**Added:** + +* + +**Changed:** + +* + +**Deprecated:** + +* + +**Removed:** + +* + +**Fixed:** + +* Fixed incorrect quoting behaviour in `activate.xsh` for virtualenv version 20.26.6. + +**Security:** + +* diff --git a/tests/test_virtualenv_activator.py b/tests/test_virtualenv_activator.py index 345e7969d..0fc9d4bd9 100644 --- a/tests/test_virtualenv_activator.py +++ b/tests/test_virtualenv_activator.py @@ -2,12 +2,15 @@ import sys from pathlib import Path from subprocess import check_output +import pytest + from xonsh.pytest.tools import ON_WINDOWS -def test_xonsh_activator(tmp_path): +@pytest.mark.parametrize("dir_name", ["venv", "venv with space"]) +def test_xonsh_activator(tmp_path, dir_name): # Create virtualenv - venv_dir = tmp_path / "venv" + venv_dir = tmp_path / dir_name assert b"XonshActivator" in check_output( [sys.executable, "-m", "virtualenv", str(venv_dir)] ) @@ -35,7 +38,13 @@ def test_xonsh_activator(tmp_path): # Activate venv_python = check_output( - [sys.executable, "-m", "xonsh", "-c", f"source {activate_path}; which python"] + [ + sys.executable, + "-m", + "xonsh", + "-c", + f"source r'{activate_path}'; which python", + ] ).decode() assert Path(venv_python).parent == bin_path @@ -46,7 +55,7 @@ def test_xonsh_activator(tmp_path): "-m", "xonsh", "-c", - f"source {activate_path}; deactivate; " + f"source r'{activate_path}'; deactivate; " "import shutil; shutil.which('python') or shutil.which('python3')", ] ).decode() diff --git a/xonsh/virtualenv/__init__.py b/xonsh/virtualenv/__init__.py index 46a1a5bfb..70664f235 100644 --- a/xonsh/virtualenv/__init__.py +++ b/xonsh/virtualenv/__init__.py @@ -5,6 +5,11 @@ class XonshActivator(ViaTemplateActivator): def templates(self): yield "activate.xsh" + @staticmethod + def quote(string): + # leave string unchanged since we do quoting in activate.xsh (see #5699) + return string + @classmethod def supports(cls, interpreter): return interpreter.version_info >= (3, 5)