Use double quoted arguments instead of executable arg

The first argument of a command line uses simpler quoting rules, so we
can actually safely build up the string just by double quoting
sys.executable.
This commit is contained in:
Paul O'Leary McCann 2022-09-30 13:18:40 +09:00
parent 71c71d3760
commit 588cb99317
2 changed files with 9 additions and 13 deletions

View File

@ -176,7 +176,6 @@ def run_commands(
""" """
for c in commands: for c in commands:
command: Union[str, List[str]] command: Union[str, List[str]]
exe: Optional[str] = None
if is_windows: if is_windows:
command = c command = c
@ -184,17 +183,18 @@ def run_commands(
# cases. It will work in ordinary cases, but will miss cases where # cases. It will work in ordinary cases, but will miss cases where
# the command is like: # the command is like:
# "C:\My Programs\python.exe" script.py # "C:\My Programs\python.exe" script.py
# In a "missed" case the command will simply be executed unchanged.
head, _, tail = c.partition(" ") head, _, tail = c.partition(" ")
# This doesn't rewrite the command to include sys.executable # Actual Windows quoting is more complicated, but simpler quoting
# because sys.executable might include spaces, quotes, or # rules are used for the first argument in command invocations.
# something, and need quoting itself. Instead the exe param is used #
# to directly specify the binary to call. # https://learn.microsoft.com/en-us/cpp/c-language/parsing-c-command-line-arguments
quoted_exe = f'"{sys.executable}"'
if head in ("python", "python3"): if head in ("python", "python3"):
exe = sys.executable command = f"{quoted_exe} {tail}"
if head in ("pip", "pip3"): if head in ("pip", "pip3"):
exe = sys.executable command = f"{quoted_exe} -m pip {tail}"
command = "python -m pip " + tail
if not silent: if not silent:
print(f"Running command: {command}") print(f"Running command: {command}")
@ -215,7 +215,7 @@ def run_commands(
print(f"Running command: {c}") print(f"Running command: {c}")
if not dry: if not dry:
run_command(command, capture=capture, exe=exe) run_command(command, capture=capture)
def validate_subcommand( def validate_subcommand(

View File

@ -944,7 +944,6 @@ def run_command(
*, *,
stdin: Optional[Any] = None, stdin: Optional[Any] = None,
capture: bool = False, capture: bool = False,
exe: Optional[str] = None,
) -> subprocess.CompletedProcess: ) -> subprocess.CompletedProcess:
"""Run a command on the command line as a subprocess. If the subprocess """Run a command on the command line as a subprocess. If the subprocess
returns a non-zero exit code, a system exit is performed. returns a non-zero exit code, a system exit is performed.
@ -956,8 +955,6 @@ def run_command(
sys.exit will be called with the return code. You should use capture=False sys.exit will be called with the return code. You should use capture=False
when you want to turn over execution to the command, and capture=True when you want to turn over execution to the command, and capture=True
when you want to run the command more like a function. when you want to run the command more like a function.
exe (Optional[str]): Path to Python executable to use. Passed separately
from the command on Windows to avoid quoting issues.
RETURNS (Optional[CompletedProcess]): The process object. RETURNS (Optional[CompletedProcess]): The process object.
""" """
@ -996,7 +993,6 @@ def run_command(
input=stdin, input=stdin,
encoding="utf8", encoding="utf8",
check=False, check=False,
executable=exe,
stdout=subprocess.PIPE if capture else None, stdout=subprocess.PIPE if capture else None,
stderr=subprocess.STDOUT if capture else None, stderr=subprocess.STDOUT if capture else None,
) )