|
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_module,
|
@@ -85,6 +86,10 @@ def get_text_file_contents(self, *args, encoding='utf-8'):
|
85 | 86 | result = f.read()
|
86 | 87 | return result
|
87 | 88 |
|
| 89 | + def assertEndsWith(self, string, tail): |
| 90 | + if not string.endswith(tail): |
| 91 | + self.fail(f"String {string!r} does not end with {tail!r}") |
| 92 | + |
88 | 93 | class BasicTest(BaseTest):
|
89 | 94 | """Test venv module functionality."""
|
90 | 95 |
|
@@ -342,6 +347,82 @@ def test_executable_symlinks(self):
|
342 | 347 | 'import sys; print(sys.executable)'])
|
343 | 348 | self.assertEqual(out.strip(), envpy.encode())
|
344 | 349 |
|
| 350 | + # gh-124651: test quoted strings |
| 351 | + @unittest.skipIf(os.name == 'nt', 'contains invalid characters on Windows') |
| 352 | + def test_special_chars_bash(self): |
| 353 | + """ |
| 354 | + Test that the template strings are quoted properly (bash) |
| 355 | + """ |
| 356 | + rmtree(self.env_dir) |
| 357 | + bash = shutil.which('bash') |
| 358 | + if bash is None: |
| 359 | + self.skipTest('bash required for this test') |
| 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') |
| 365 | + test_script = os.path.join(self.env_dir, 'test_special_chars.sh') |
| 366 | + with open(test_script, "w") as f: |
| 367 | + f.write(f'source {shlex.quote(activate)}\n' |
| 368 | + 'python -c \'import sys; print(sys.executable)\'\n' |
| 369 | + 'python -c \'import os; print(os.environ["VIRTUAL_ENV"])\'\n' |
| 370 | + 'deactivate\n') |
| 371 | + out, err = check_output([bash, test_script]) |
| 372 | + lines = out.splitlines() |
| 373 | + self.assertTrue(env_name.encode() in lines[0]) |
| 374 | + self.assertEndsWith(lines[1], env_name.encode()) |
| 375 | + |
| 376 | + # gh-124651: test quoted strings |
| 377 | + @unittest.skipIf(os.name == 'nt', 'contains invalid characters on Windows') |
| 378 | + def test_special_chars_csh(self): |
| 379 | + """ |
| 380 | + Test that the template strings are quoted properly (csh) |
| 381 | + """ |
| 382 | + rmtree(self.env_dir) |
| 383 | + csh = shutil.which('tcsh') or shutil.which('csh') |
| 384 | + if csh is None: |
| 385 | + self.skipTest('csh required for this test') |
| 386 | + env_name = '"\';&&$e|\'"' |
| 387 | + env_dir = os.path.join(os.path.realpath(self.env_dir), env_name) |
| 388 | + builder = venv.EnvBuilder(clear=True) |
| 389 | + builder.create(env_dir) |
| 390 | + activate = os.path.join(env_dir, self.bindir, 'activate.csh') |
| 391 | + test_script = os.path.join(self.env_dir, 'test_special_chars.csh') |
| 392 | + with open(test_script, "w") as f: |
| 393 | + f.write(f'source {shlex.quote(activate)}\n' |
| 394 | + 'python -c \'import sys; print(sys.executable)\'\n' |
| 395 | + 'python -c \'import os; print(os.environ["VIRTUAL_ENV"])\'\n' |
| 396 | + 'deactivate\n') |
| 397 | + out, err = check_output([csh, test_script]) |
| 398 | + lines = out.splitlines() |
| 399 | + self.assertTrue(env_name.encode() in lines[0]) |
| 400 | + self.assertEndsWith(lines[1], env_name.encode()) |
| 401 | + |
| 402 | + # gh-124651: test quoted strings on Windows |
| 403 | + @unittest.skipUnless(os.name == 'nt', 'only relevant on Windows') |
| 404 | + def test_special_chars_windows(self): |
| 405 | + """ |
| 406 | + Test that the template strings are quoted properly on Windows |
| 407 | + """ |
| 408 | + rmtree(self.env_dir) |
| 409 | + env_name = "'&&^$e" |
| 410 | + env_dir = os.path.join(os.path.realpath(self.env_dir), env_name) |
| 411 | + builder = venv.EnvBuilder(clear=True) |
| 412 | + builder.create(env_dir) |
| 413 | + activate = os.path.join(env_dir, self.bindir, 'activate.bat') |
| 414 | + test_batch = os.path.join(self.env_dir, 'test_special_chars.bat') |
| 415 | + with open(test_batch, "w") as f: |
| 416 | + f.write('@echo off\n' |
| 417 | + f'"{activate}" & ' |
| 418 | + f'{self.exe} -c "import sys; print(sys.executable)" & ' |
| 419 | + f'{self.exe} -c "import os; print(os.environ[\'VIRTUAL_ENV\'])" & ' |
| 420 | + 'deactivate') |
| 421 | + out, err = check_output([test_batch]) |
| 422 | + lines = out.splitlines() |
| 423 | + self.assertTrue(env_name.encode() in lines[0]) |
| 424 | + self.assertEndsWith(lines[1], env_name.encode()) |
| 425 | + |
345 | 426 | @unittest.skipUnless(os.name == 'nt', 'only relevant on Windows')
|
346 | 427 | def test_unicode_in_batch_file(self):
|
347 | 428 | """
|
|
0 commit comments