|
17 | 17 | import sys
|
18 | 18 | import sysconfig
|
19 | 19 | import tempfile
|
20 |
| -from test.support import (captured_stdout, captured_stderr, requires_zlib, |
| 20 | +import shlex |
| 21 | +from test.support import (captured_stdout, captured_stderr, |
21 | 22 | skip_if_broken_multiprocessing_synchronize, verbose,
|
22 | 23 | requires_subprocess, is_emscripten, is_wasi,
|
23 | 24 | requires_venv_with_pip, TEST_HOME_DIR,
|
@@ -96,6 +97,10 @@ def get_text_file_contents(self, *args, encoding='utf-8'):
|
96 | 97 | result = f.read()
|
97 | 98 | return result
|
98 | 99 |
|
| 100 | + def assertEndsWith(self, string, tail): |
| 101 | + if not string.endswith(tail): |
| 102 | + self.fail(f"String {string!r} does not end with {tail!r}") |
| 103 | + |
99 | 104 | class BasicTest(BaseTest):
|
100 | 105 | """Test venv module functionality."""
|
101 | 106 |
|
@@ -446,6 +451,82 @@ def test_executable_symlinks(self):
|
446 | 451 | 'import sys; print(sys.executable)'])
|
447 | 452 | self.assertEqual(out.strip(), envpy.encode())
|
448 | 453 |
|
| 454 | + # gh-124651: test quoted strings |
| 455 | + @unittest.skipIf(os.name == 'nt', 'contains invalid characters on Windows') |
| 456 | + def test_special_chars_bash(self): |
| 457 | + """ |
| 458 | + Test that the template strings are quoted properly (bash) |
| 459 | + """ |
| 460 | + rmtree(self.env_dir) |
| 461 | + bash = shutil.which('bash') |
| 462 | + if bash is None: |
| 463 | + self.skipTest('bash required for this test') |
| 464 | + env_name = '"\';&&$e|\'"' |
| 465 | + env_dir = os.path.join(os.path.realpath(self.env_dir), env_name) |
| 466 | + builder = venv.EnvBuilder(clear=True) |
| 467 | + builder.create(env_dir) |
| 468 | + activate = os.path.join(env_dir, self.bindir, 'activate') |
| 469 | + test_script = os.path.join(self.env_dir, 'test_special_chars.sh') |
| 470 | + with open(test_script, "w") as f: |
| 471 | + f.write(f'source {shlex.quote(activate)}\n' |
| 472 | + 'python -c \'import sys; print(sys.executable)\'\n' |
| 473 | + 'python -c \'import os; print(os.environ["VIRTUAL_ENV"])\'\n' |
| 474 | + 'deactivate\n') |
| 475 | + out, err = check_output([bash, test_script]) |
| 476 | + lines = out.splitlines() |
| 477 | + self.assertTrue(env_name.encode() in lines[0]) |
| 478 | + self.assertEndsWith(lines[1], env_name.encode()) |
| 479 | + |
| 480 | + # gh-124651: test quoted strings |
| 481 | + @unittest.skipIf(os.name == 'nt', 'contains invalid characters on Windows') |
| 482 | + def test_special_chars_csh(self): |
| 483 | + """ |
| 484 | + Test that the template strings are quoted properly (csh) |
| 485 | + """ |
| 486 | + rmtree(self.env_dir) |
| 487 | + csh = shutil.which('tcsh') or shutil.which('csh') |
| 488 | + if csh is None: |
| 489 | + self.skipTest('csh required for this test') |
| 490 | + env_name = '"\';&&$e|\'"' |
| 491 | + env_dir = os.path.join(os.path.realpath(self.env_dir), env_name) |
| 492 | + builder = venv.EnvBuilder(clear=True) |
| 493 | + builder.create(env_dir) |
| 494 | + activate = os.path.join(env_dir, self.bindir, 'activate.csh') |
| 495 | + test_script = os.path.join(self.env_dir, 'test_special_chars.csh') |
| 496 | + with open(test_script, "w") as f: |
| 497 | + f.write(f'source {shlex.quote(activate)}\n' |
| 498 | + 'python -c \'import sys; print(sys.executable)\'\n' |
| 499 | + 'python -c \'import os; print(os.environ["VIRTUAL_ENV"])\'\n' |
| 500 | + 'deactivate\n') |
| 501 | + out, err = check_output([csh, test_script]) |
| 502 | + lines = out.splitlines() |
| 503 | + self.assertTrue(env_name.encode() in lines[0]) |
| 504 | + self.assertEndsWith(lines[1], env_name.encode()) |
| 505 | + |
| 506 | + # gh-124651: test quoted strings on Windows |
| 507 | + @unittest.skipUnless(os.name == 'nt', 'only relevant on Windows') |
| 508 | + def test_special_chars_windows(self): |
| 509 | + """ |
| 510 | + Test that the template strings are quoted properly on Windows |
| 511 | + """ |
| 512 | + rmtree(self.env_dir) |
| 513 | + env_name = "'&&^$e" |
| 514 | + env_dir = os.path.join(os.path.realpath(self.env_dir), env_name) |
| 515 | + builder = venv.EnvBuilder(clear=True) |
| 516 | + builder.create(env_dir) |
| 517 | + activate = os.path.join(env_dir, self.bindir, 'activate.bat') |
| 518 | + test_batch = os.path.join(self.env_dir, 'test_special_chars.bat') |
| 519 | + with open(test_batch, "w") as f: |
| 520 | + f.write('@echo off\n' |
| 521 | + f'"{activate}" & ' |
| 522 | + f'{self.exe} -c "import sys; print(sys.executable)" & ' |
| 523 | + f'{self.exe} -c "import os; print(os.environ[\'VIRTUAL_ENV\'])" & ' |
| 524 | + 'deactivate') |
| 525 | + out, err = check_output([test_batch]) |
| 526 | + lines = out.splitlines() |
| 527 | + self.assertTrue(env_name.encode() in lines[0]) |
| 528 | + self.assertEndsWith(lines[1], env_name.encode()) |
| 529 | + |
449 | 530 | @unittest.skipUnless(os.name == 'nt', 'only relevant on Windows')
|
450 | 531 | def test_unicode_in_batch_file(self):
|
451 | 532 | """
|
|
0 commit comments