|
17 | 17 | import sys
|
18 | 18 | import sysconfig
|
19 | 19 | import tempfile
|
| 20 | +import shlex |
20 | 21 | from test.support import (captured_stdout, captured_stderr,
|
21 | 22 | skip_if_broken_multiprocessing_synchronize, verbose,
|
22 | 23 | requires_subprocess, is_android, is_apple_mobile,
|
@@ -110,6 +111,10 @@ def get_text_file_contents(self, *args, encoding='utf-8'):
|
110 | 111 | result = f.read()
|
111 | 112 | return result
|
112 | 113 |
|
| 114 | + def assertEndsWith(self, string, tail): |
| 115 | + if not string.endswith(tail): |
| 116 | + self.fail(f"String {string!r} does not end with {tail!r}") |
| 117 | + |
113 | 118 | class BasicTest(BaseTest):
|
114 | 119 | """Test venv module functionality."""
|
115 | 120 |
|
@@ -488,6 +493,82 @@ def test_executable_symlinks(self):
|
488 | 493 | 'import sys; print(sys.executable)'])
|
489 | 494 | self.assertEqual(out.strip(), envpy.encode())
|
490 | 495 |
|
| 496 | + # gh-124651: test quoted strings |
| 497 | + @unittest.skipIf(os.name == 'nt', 'contains invalid characters on Windows') |
| 498 | + def test_special_chars_bash(self): |
| 499 | + """ |
| 500 | + Test that the template strings are quoted properly (bash) |
| 501 | + """ |
| 502 | + rmtree(self.env_dir) |
| 503 | + bash = shutil.which('bash') |
| 504 | + if bash is None: |
| 505 | + self.skipTest('bash required for this test') |
| 506 | + env_name = '"\';&&$e|\'"' |
| 507 | + env_dir = os.path.join(os.path.realpath(self.env_dir), env_name) |
| 508 | + builder = venv.EnvBuilder(clear=True) |
| 509 | + builder.create(env_dir) |
| 510 | + activate = os.path.join(env_dir, self.bindir, 'activate') |
| 511 | + test_script = os.path.join(self.env_dir, 'test_special_chars.sh') |
| 512 | + with open(test_script, "w") as f: |
| 513 | + f.write(f'source {shlex.quote(activate)}\n' |
| 514 | + 'python -c \'import sys; print(sys.executable)\'\n' |
| 515 | + 'python -c \'import os; print(os.environ["VIRTUAL_ENV"])\'\n' |
| 516 | + 'deactivate\n') |
| 517 | + out, err = check_output([bash, test_script]) |
| 518 | + lines = out.splitlines() |
| 519 | + self.assertTrue(env_name.encode() in lines[0]) |
| 520 | + self.assertEndsWith(lines[1], env_name.encode()) |
| 521 | + |
| 522 | + # gh-124651: test quoted strings |
| 523 | + @unittest.skipIf(os.name == 'nt', 'contains invalid characters on Windows') |
| 524 | + def test_special_chars_csh(self): |
| 525 | + """ |
| 526 | + Test that the template strings are quoted properly (csh) |
| 527 | + """ |
| 528 | + rmtree(self.env_dir) |
| 529 | + csh = shutil.which('tcsh') or shutil.which('csh') |
| 530 | + if csh is None: |
| 531 | + self.skipTest('csh required for this test') |
| 532 | + env_name = '"\';&&$e|\'"' |
| 533 | + env_dir = os.path.join(os.path.realpath(self.env_dir), env_name) |
| 534 | + builder = venv.EnvBuilder(clear=True) |
| 535 | + builder.create(env_dir) |
| 536 | + activate = os.path.join(env_dir, self.bindir, 'activate.csh') |
| 537 | + test_script = os.path.join(self.env_dir, 'test_special_chars.csh') |
| 538 | + with open(test_script, "w") as f: |
| 539 | + f.write(f'source {shlex.quote(activate)}\n' |
| 540 | + 'python -c \'import sys; print(sys.executable)\'\n' |
| 541 | + 'python -c \'import os; print(os.environ["VIRTUAL_ENV"])\'\n' |
| 542 | + 'deactivate\n') |
| 543 | + out, err = check_output([csh, test_script]) |
| 544 | + lines = out.splitlines() |
| 545 | + self.assertTrue(env_name.encode() in lines[0]) |
| 546 | + self.assertEndsWith(lines[1], env_name.encode()) |
| 547 | + |
| 548 | + # gh-124651: test quoted strings on Windows |
| 549 | + @unittest.skipUnless(os.name == 'nt', 'only relevant on Windows') |
| 550 | + def test_special_chars_windows(self): |
| 551 | + """ |
| 552 | + Test that the template strings are quoted properly on Windows |
| 553 | + """ |
| 554 | + rmtree(self.env_dir) |
| 555 | + env_name = "'&&^$e" |
| 556 | + env_dir = os.path.join(os.path.realpath(self.env_dir), env_name) |
| 557 | + builder = venv.EnvBuilder(clear=True) |
| 558 | + builder.create(env_dir) |
| 559 | + activate = os.path.join(env_dir, self.bindir, 'activate.bat') |
| 560 | + test_batch = os.path.join(self.env_dir, 'test_special_chars.bat') |
| 561 | + with open(test_batch, "w") as f: |
| 562 | + f.write('@echo off\n' |
| 563 | + f'"{activate}" & ' |
| 564 | + f'{self.exe} -c "import sys; print(sys.executable)" & ' |
| 565 | + f'{self.exe} -c "import os; print(os.environ[\'VIRTUAL_ENV\'])" & ' |
| 566 | + 'deactivate') |
| 567 | + out, err = check_output([test_batch]) |
| 568 | + lines = out.splitlines() |
| 569 | + self.assertTrue(env_name.encode() in lines[0]) |
| 570 | + self.assertEndsWith(lines[1], env_name.encode()) |
| 571 | + |
491 | 572 | @unittest.skipUnless(os.name == 'nt', 'only relevant on Windows')
|
492 | 573 | def test_unicode_in_batch_file(self):
|
493 | 574 | """
|
|
0 commit comments