https://github.com/python/cpython/commit/d3a1e7280bd74a16c5822cff9c77fa28da4d725e
commit: d3a1e7280bd74a16c5822cff9c77fa28da4d725e
branch: main
author: Neko Asakura <[email protected]>
committer: vsajip <[email protected]>
date: 2026-10-30T09:26:32Z
summary:

gh-160782: fix fish quote-escaping gap (GH-160943)

files:
A Misc/NEWS.d/next/Library/2026-10-29-23-25-31.gh-issue-160782.1ZwCOr.rst
M Lib/test/test_venv.py
M Lib/venv/__init__.py

diff --git a/Lib/test/test_venv.py b/Lib/test/test_venv.py
index a7595967ba8141a..678615ea172aefa 100644
--- a/Lib/test/test_venv.py
+++ b/Lib/test/test_venv.py
@@ -846,6 +846,18 @@ def test_fish_activate_shadowed_builtins(self):
         self.assertNotIn('LEAK', text)
         self.assertIn('OLDSTATUS=7', text)
 
+    def test_fish_quoting(self):
+        """
+        Test that the template strings are quoted properly (fish)
+        """
+        builder = venv.EnvBuilder()
+        context = builder.ensure_directories(self.env_dir)
+        context.script_path = 'activate.fish'
+        context.prompt = r"x\'$(echo PWNED)'\'"
+        self.assertEqual(
+            builder.replace_variables('__VENV_PROMPT__', context),
+            r"'x\\\'$(echo PWNED)\'\\\''")
+
     # gh-124651: test quoted strings on Windows
     @unittest.skipUnless(os.name == 'nt', 'only relevant on Windows')
     def test_special_chars_windows(self):
diff --git a/Lib/venv/__init__.py b/Lib/venv/__init__.py
index fc55c248cd54f90..620168be16862ec 100644
--- a/Lib/venv/__init__.py
+++ b/Lib/venv/__init__.py
@@ -521,6 +521,11 @@ def quote_ps1(s):
         def quote_bat(s):
             return s
 
+        def quote_fish(s):
+            # gh-160782: fish reads \\ and \' as escapes inside single quotes
+            s = s.replace('\\', '\\\\').replace("'", "\\'")
+            return f"'{s}'"
+
         # gh-124651: need to quote the template strings properly
         quote = shlex.quote
         script_path = context.script_path
@@ -528,6 +533,8 @@ def quote_bat(s):
             quote = quote_ps1
         elif script_path.endswith('.bat'):
             quote = quote_bat
+        elif script_path.endswith('.fish'):
+            quote = quote_fish
         else:
             # fallbacks to POSIX shell compliant quote
             quote = shlex.quote
diff --git 
a/Misc/NEWS.d/next/Library/2026-10-29-23-25-31.gh-issue-160782.1ZwCOr.rst 
b/Misc/NEWS.d/next/Library/2026-10-29-23-25-31.gh-issue-160782.1ZwCOr.rst
new file mode 100644
index 000000000000000..57ff63c1f6d3f7e
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2026-10-29-23-25-31.gh-issue-160782.1ZwCOr.rst
@@ -0,0 +1,2 @@
+:mod:`venv`: a backslash before a quote in the prompt or the path no longer
+breaks ``activate.fish``.

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]

Reply via email to