|
14 | 14 | import subprocess
|
15 | 15 | import sys
|
16 | 16 | import tempfile
|
| 17 | +import shlex |
17 | 18 | from test.support import (captured_stdout, captured_stderr, requires_zlib,
|
18 | 19 | can_symlink, EnvironmentVarGuard, rmtree)
|
19 | 20 | import threading
|
@@ -83,6 +84,10 @@ def get_text_file_contents(self, *args):
|
83 | 84 | result = f.read()
|
84 | 85 | return result
|
85 | 86 |
|
| 87 | + def assertEndsWith(self, string, tail): |
| 88 | + if not string.endswith(tail): |
| 89 | + self.fail(f"String {string!r} does not end with {tail!r}") |
| 90 | + |
86 | 91 | class BasicTest(BaseTest):
|
87 | 92 | """Test venv module functionality."""
|
88 | 93 |
|
@@ -293,6 +298,82 @@ def test_executable_symlinks(self):
|
293 | 298 | 'import sys; print(sys.executable)'])
|
294 | 299 | self.assertEqual(out.strip(), envpy.encode())
|
295 | 300 |
|
| 301 | + # gh-124651: test quoted strings |
| 302 | + @unittest.skipIf(os.name == 'nt', 'contains invalid characters on Windows') |
| 303 | + def test_special_chars_bash(self): |
| 304 | + """ |
| 305 | + Test that the template strings are quoted properly (bash) |
| 306 | + """ |
| 307 | + rmtree(self.env_dir) |
| 308 | + bash = shutil.which('bash') |
| 309 | + if bash is None: |
| 310 | + self.skipTest('bash required for this test') |
| 311 | + env_name = '"\';&&$e|\'"' |
| 312 | + env_dir = os.path.join(os.path.realpath(self.env_dir), env_name) |
| 313 | + builder = venv.EnvBuilder(clear=True) |
| 314 | + builder.create(env_dir) |
| 315 | + activate = os.path.join(env_dir, self.bindir, 'activate') |
| 316 | + test_script = os.path.join(self.env_dir, 'test_special_chars.sh') |
| 317 | + with open(test_script, "w") as f: |
| 318 | + f.write(f'source {shlex.quote(activate)}\n' |
| 319 | + 'python -c \'import sys; print(sys.executable)\'\n' |
| 320 | + 'python -c \'import os; print(os.environ["VIRTUAL_ENV"])\'\n' |
| 321 | + 'deactivate\n') |
| 322 | + out, err = check_output([bash, test_script]) |
| 323 | + lines = out.splitlines() |
| 324 | + self.assertTrue(env_name.encode() in lines[0]) |
| 325 | + self.assertEndsWith(lines[1], env_name.encode()) |
| 326 | + |
| 327 | + # gh-124651: test quoted strings |
| 328 | + @unittest.skipIf(os.name == 'nt', 'contains invalid characters on Windows') |
| 329 | + def test_special_chars_csh(self): |
| 330 | + """ |
| 331 | + Test that the template strings are quoted properly (csh) |
| 332 | + """ |
| 333 | + rmtree(self.env_dir) |
| 334 | + csh = shutil.which('tcsh') or shutil.which('csh') |
| 335 | + if csh is None: |
| 336 | + self.skipTest('csh required for this test') |
| 337 | + env_name = '"\';&&$e|\'"' |
| 338 | + env_dir = os.path.join(os.path.realpath(self.env_dir), env_name) |
| 339 | + builder = venv.EnvBuilder(clear=True) |
| 340 | + builder.create(env_dir) |
| 341 | + activate = os.path.join(env_dir, self.bindir, 'activate.csh') |
| 342 | + test_script = os.path.join(self.env_dir, 'test_special_chars.csh') |
| 343 | + with open(test_script, "w") as f: |
| 344 | + f.write(f'source {shlex.quote(activate)}\n' |
| 345 | + 'python -c \'import sys; print(sys.executable)\'\n' |
| 346 | + 'python -c \'import os; print(os.environ["VIRTUAL_ENV"])\'\n' |
| 347 | + 'deactivate\n') |
| 348 | + out, err = check_output([csh, test_script]) |
| 349 | + lines = out.splitlines() |
| 350 | + self.assertTrue(env_name.encode() in lines[0]) |
| 351 | + self.assertEndsWith(lines[1], env_name.encode()) |
| 352 | + |
| 353 | + # gh-124651: test quoted strings on Windows |
| 354 | + @unittest.skipUnless(os.name == 'nt', 'only relevant on Windows') |
| 355 | + def test_special_chars_windows(self): |
| 356 | + """ |
| 357 | + Test that the template strings are quoted properly on Windows |
| 358 | + """ |
| 359 | + rmtree(self.env_dir) |
| 360 | + env_name = "'&&^$e" |
| 361 | + env_dir = os.path.join(os.path.realpath(self.env_dir), env_name) |
| 362 | + builder = venv.EnvBuilder(clear=True) |
| 363 | + builder.create(env_dir) |
| 364 | + activate = os.path.join(env_dir, self.bindir, 'activate.bat') |
| 365 | + test_batch = os.path.join(self.env_dir, 'test_special_chars.bat') |
| 366 | + with open(test_batch, "w") as f: |
| 367 | + f.write('@echo off\n' |
| 368 | + f'"{activate}" & ' |
| 369 | + f'{self.exe} -c "import sys; print(sys.executable)" & ' |
| 370 | + f'{self.exe} -c "import os; print(os.environ[\'VIRTUAL_ENV\'])" & ' |
| 371 | + 'deactivate') |
| 372 | + out, err = check_output([test_batch]) |
| 373 | + lines = out.splitlines() |
| 374 | + self.assertTrue(env_name.encode() in lines[0]) |
| 375 | + self.assertEndsWith(lines[1], env_name.encode()) |
| 376 | + |
296 | 377 | @unittest.skipUnless(os.name == 'nt', 'only relevant on Windows')
|
297 | 378 | def test_unicode_in_batch_file(self):
|
298 | 379 | """
|
|
0 commit comments