Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit6335557

Browse files
authored
[3.9]gh-124651: Quote template strings invenv activation scripts (GH-124712) (GH-126185) (GH-126269) (GH-126301)
(cherry picked from commitae961ae)
1 parentbbe8756 commit6335557

File tree

7 files changed

+130
-16
lines changed

7 files changed

+130
-16
lines changed

‎Lib/test/test_venv.py

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
importsubprocess
1515
importsys
1616
importtempfile
17+
importshlex
1718
fromtest.supportimport (captured_stdout,captured_stderr,requires_zlib,
1819
can_symlink,EnvironmentVarGuard,rmtree,
1920
import_module,
@@ -85,6 +86,10 @@ def get_text_file_contents(self, *args, encoding='utf-8'):
8586
result=f.read()
8687
returnresult
8788

89+
defassertEndsWith(self,string,tail):
90+
ifnotstring.endswith(tail):
91+
self.fail(f"String{string!r} does not end with{tail!r}")
92+
8893
classBasicTest(BaseTest):
8994
"""Test venv module functionality."""
9095

@@ -342,6 +347,82 @@ def test_executable_symlinks(self):
342347
'import sys; print(sys.executable)'])
343348
self.assertEqual(out.strip(),envpy.encode())
344349

350+
# gh-124651: test quoted strings
351+
@unittest.skipIf(os.name=='nt','contains invalid characters on Windows')
352+
deftest_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+
ifbashisNone:
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+
withopen(test_script,"w")asf:
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()inlines[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+
deftest_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')orshutil.which('csh')
384+
ifcshisNone:
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+
withopen(test_script,"w")asf:
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()inlines[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+
deftest_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+
withopen(test_batch,"w")asf:
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()inlines[0])
424+
self.assertEndsWith(lines[1],env_name.encode())
425+
345426
@unittest.skipUnless(os.name=='nt','only relevant on Windows')
346427
deftest_unicode_in_batch_file(self):
347428
"""

‎Lib/venv/__init__.py

Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
importsys
1212
importsysconfig
1313
importtypes
14+
importshlex
1415

1516

1617
CORE_VENV_DEPS= ('pip','setuptools')
@@ -348,11 +349,41 @@ def replace_variables(self, text, context):
348349
:param context: The information for the environment creation request
349350
being processed.
350351
"""
351-
text=text.replace('__VENV_DIR__',context.env_dir)
352-
text=text.replace('__VENV_NAME__',context.env_name)
353-
text=text.replace('__VENV_PROMPT__',context.prompt)
354-
text=text.replace('__VENV_BIN_NAME__',context.bin_name)
355-
text=text.replace('__VENV_PYTHON__',context.env_exe)
352+
replacements= {
353+
'__VENV_DIR__':context.env_dir,
354+
'__VENV_NAME__':context.env_name,
355+
'__VENV_PROMPT__':context.prompt,
356+
'__VENV_BIN_NAME__':context.bin_name,
357+
'__VENV_PYTHON__':context.env_exe,
358+
}
359+
360+
defquote_ps1(s):
361+
"""
362+
This should satisfy PowerShell quoting rules [1], unless the quoted
363+
string is passed directly to Windows native commands [2].
364+
[1]: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_quoting_rules
365+
[2]: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_parsing#passing-arguments-that-contain-quote-characters
366+
"""
367+
s=s.replace("'","''")
368+
returnf"'{s}'"
369+
370+
defquote_bat(s):
371+
returns
372+
373+
# gh-124651: need to quote the template strings properly
374+
quote=shlex.quote
375+
script_path=context.script_path
376+
ifscript_path.endswith('.ps1'):
377+
quote=quote_ps1
378+
elifscript_path.endswith('.bat'):
379+
quote=quote_bat
380+
else:
381+
# fallbacks to POSIX shell compliant quote
382+
quote=shlex.quote
383+
384+
replacements= {key:quote(s)forkey,sinreplacements.items()}
385+
forkey,quotedinreplacements.items():
386+
text=text.replace(key,quoted)
356387
returntext
357388

358389
definstall_scripts(self,context,path):
@@ -392,6 +423,7 @@ def install_scripts(self, context, path):
392423
withopen(srcfile,'rb')asf:
393424
data=f.read()
394425
ifnotsrcfile.endswith(('.exe','.pdb')):
426+
context.script_path=srcfile
395427
try:
396428
data=data.decode('utf-8')
397429
data=self.replace_variables(data,context)

‎Lib/venv/scripts/common/activate

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,11 @@ deactivate () {
3737
# unset irrelevant variables
3838
deactivate nondestructive
3939

40-
VIRTUAL_ENV="__VENV_DIR__"
40+
VIRTUAL_ENV=__VENV_DIR__
4141
export VIRTUAL_ENV
4242

4343
_OLD_VIRTUAL_PATH="$PATH"
44-
PATH="$VIRTUAL_ENV/__VENV_BIN_NAME__:$PATH"
44+
PATH="$VIRTUAL_ENV/"__VENV_BIN_NAME__":$PATH"
4545
export PATH
4646

4747
# unset PYTHONHOME if set
@@ -54,7 +54,7 @@ fi
5454

5555
if [ -z "${VIRTUAL_ENV_DISABLE_PROMPT:-}" ] ; then
5656
_OLD_VIRTUAL_PS1="${PS1:-}"
57-
PS1="__VENV_PROMPT__${PS1:-}"
57+
PS1=__VENV_PROMPT__"${PS1:-}"
5858
export PS1
5959
fi
6060

‎Lib/venv/scripts/nt/activate.bat

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ if defined _OLD_CODEPAGE (
88
"%SystemRoot%\System32\chcp.com"65001>nul
99
)
1010

11-
setVIRTUAL_ENV=__VENV_DIR__
11+
set"VIRTUAL_ENV=__VENV_DIR__"
1212

1313
ifnotdefinedPROMPTsetPROMPT=$P$G
1414

@@ -24,7 +24,7 @@ set PYTHONHOME=
2424
ifdefined _OLD_VIRTUAL_PATHsetPATH=%_OLD_VIRTUAL_PATH%
2525
ifnotdefined _OLD_VIRTUAL_PATHset_OLD_VIRTUAL_PATH=%PATH%
2626

27-
setPATH=%VIRTUAL_ENV%\__VENV_BIN_NAME__;%PATH%
27+
set"PATH=%VIRTUAL_ENV%\__VENV_BIN_NAME__;%PATH%"
2828

2929
:END
3030
ifdefined _OLD_CODEPAGE (

‎Lib/venv/scripts/posix/activate.csh

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,16 @@ alias deactivate 'test $?_OLD_VIRTUAL_PATH != 0 && setenv PATH "$_OLD_VIRTUAL_PA
88
# Unset irrelevant variables.
99
deactivate nondestructive
1010

11-
setenv VIRTUAL_ENV"__VENV_DIR__"
11+
setenv VIRTUAL_ENV __VENV_DIR__
1212

1313
set _OLD_VIRTUAL_PATH="$PATH"
14-
setenv PATH"$VIRTUAL_ENV/__VENV_BIN_NAME__:$PATH"
14+
setenv PATH"$VIRTUAL_ENV/"__VENV_BIN_NAME__":$PATH"
1515

1616

1717
set _OLD_VIRTUAL_PROMPT="$prompt"
1818

1919
if (!"$?VIRTUAL_ENV_DISABLE_PROMPT")then
20-
set prompt ="__VENV_PROMPT__$prompt"
20+
set prompt = __VENV_PROMPT__"$prompt"
2121
endif
2222

2323
alias pydoc python -m pydoc

‎Lib/venv/scripts/posix/activate.fish

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,10 @@ end
2929
# Unset irrelevant variables.
3030
deactivate nondestructive
3131

32-
set-gx VIRTUAL_ENV"__VENV_DIR__"
32+
set-gx VIRTUAL_ENV __VENV_DIR__
3333

3434
set-gx _OLD_VIRTUAL_PATH$PATH
35-
set-gx PATH"$VIRTUAL_ENV/__VENV_BIN_NAME__"$PATH
35+
set-gx PATH"$VIRTUAL_ENV/"__VENV_BIN_NAME__$PATH
3636

3737
# Unset PYTHONHOME if set.
3838
ifset-q PYTHONHOME
@@ -52,7 +52,7 @@ if test -z "$VIRTUAL_ENV_DISABLE_PROMPT"
5252
set-l old_status$status
5353

5454
# Output the venv prompt; color taken from the blue of the Python logo.
55-
printf"%s%s%s" (set_color 4B8BBE)"__VENV_PROMPT__" (set_color normal)
55+
printf"%s%s%s" (set_color 4B8BBE) __VENV_PROMPT__ (set_color normal)
5656

5757
# Restore the return status of the previous command.
5858
echo"exit$old_status"| .
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Properly quote template strings in:mod:`venv` activation scripts.

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp