summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorHarmen Stoppels <me@harmenstoppels.nl>2024-09-06 13:38:14 +0200
committerGitHub <noreply@github.com>2024-09-06 11:38:14 +0000
commit7fdf1029b747555f1d3040075bfeaf322ee6837e (patch)
treeeee6f0c92c543f4cc98eab56bb21840794f9b6a2 /lib
parent814f4f20c0dda13cc5668bb26ef9d09e876a5d75 (diff)
downloadspack-7fdf1029b747555f1d3040075bfeaf322ee6837e.tar.gz
spack-7fdf1029b747555f1d3040075bfeaf322ee6837e.tar.bz2
spack-7fdf1029b747555f1d3040075bfeaf322ee6837e.tar.xz
spack-7fdf1029b747555f1d3040075bfeaf322ee6837e.zip
fish: use shlex.quote instead of custom quote (#46251)
Diffstat (limited to 'lib')
-rw-r--r--lib/spack/spack/cmd/commands.py113
1 files changed, 43 insertions, 70 deletions
diff --git a/lib/spack/spack/cmd/commands.py b/lib/spack/spack/cmd/commands.py
index c6e775dd43..a6616061ed 100644
--- a/lib/spack/spack/cmd/commands.py
+++ b/lib/spack/spack/cmd/commands.py
@@ -7,6 +7,7 @@ import argparse
import copy
import os
import re
+import shlex
import sys
from argparse import ArgumentParser, Namespace
from typing import IO, Any, Callable, Dict, Iterable, List, Optional, Sequence, Set, Tuple, Union
@@ -18,6 +19,7 @@ from llnl.util.tty.colify import colify
import spack.cmd
import spack.main
import spack.paths
+import spack.platforms
from spack.main import section_descriptions
description = "list available spack commands"
@@ -139,7 +141,7 @@ class SpackArgparseRstWriter(ArgparseRstWriter):
cmd = self.parser.prog.replace(" ", "-")
if cmd in self.documented:
- string += "\n:ref:`More documentation <cmd-{0}>`\n".format(cmd)
+ string = f"{string}\n:ref:`More documentation <cmd-{cmd}>`\n"
return string
@@ -249,33 +251,27 @@ class BashCompletionWriter(ArgparseWriter):
Function body.
"""
if positionals:
- return """
+ return f"""
if $list_options
then
- {0}
+ {self.optionals(optionals)}
else
- {1}
+ {self.positionals(positionals)}
fi
-""".format(
- self.optionals(optionals), self.positionals(positionals)
- )
+"""
elif subcommands:
- return """
+ return f"""
if $list_options
then
- {0}
+ {self.optionals(optionals)}
else
- {1}
+ {self.subcommands(subcommands)}
fi
-""".format(
- self.optionals(optionals), self.subcommands(subcommands)
- )
+"""
else:
- return """
- {0}
-""".format(
- self.optionals(optionals)
- )
+ return f"""
+ {self.optionals(optionals)}
+"""
def positionals(self, positionals: Sequence[str]) -> str:
"""Return the syntax for reporting positional arguments.
@@ -304,7 +300,7 @@ class BashCompletionWriter(ArgparseWriter):
Returns:
Syntax for optional flags.
"""
- return 'SPACK_COMPREPLY="{0}"'.format(" ".join(optionals))
+ return f'SPACK_COMPREPLY="{" ".join(optionals)}"'
def subcommands(self, subcommands: Sequence[str]) -> str:
"""Return the syntax for reporting subcommands.
@@ -315,7 +311,7 @@ class BashCompletionWriter(ArgparseWriter):
Returns:
Syntax for subcommand parsers
"""
- return 'SPACK_COMPREPLY="{0}"'.format(" ".join(subcommands))
+ return f'SPACK_COMPREPLY="{" ".join(subcommands)}"'
# Map argument destination names to their complete commands
@@ -395,7 +391,7 @@ def _fish_dest_get_complete(prog: str, dest: str) -> Optional[str]:
subcmd = s[1] if len(s) == 2 else ""
for (prog_key, pos_key), value in _dest_to_fish_complete.items():
- if subcmd.startswith(prog_key) and re.match("^" + pos_key + "$", dest):
+ if subcmd.startswith(prog_key) and re.match(f"^{pos_key}$", dest):
return value
return None
@@ -427,24 +423,6 @@ class FishCompletionWriter(ArgparseWriter):
+ self.complete(cmd.prog, positionals, optionals, subcommands)
)
- def _quote(self, string: str) -> str:
- """Quote string and escape special characters if necessary.
-
- Args:
- string: Input string.
-
- Returns:
- Quoted string.
- """
- # Goal here is to match fish_indent behavior
-
- # Strings without spaces (or other special characters) do not need to be escaped
- if not any([sub in string for sub in [" ", "'", '"']]):
- return string
-
- string = string.replace("'", r"\'")
- return f"'{string}'"
-
def optspecs(
self,
prog: str,
@@ -463,7 +441,7 @@ class FishCompletionWriter(ArgparseWriter):
optspec_var = "__fish_spack_optspecs_" + prog.replace(" ", "_").replace("-", "_")
if optionals is None:
- return "set -g %s\n" % optspec_var
+ return f"set -g {optspec_var}\n"
# Build optspec by iterating over options
args = []
@@ -490,11 +468,11 @@ class FishCompletionWriter(ArgparseWriter):
long = [f[2:] for f in flags if f.startswith("--")]
while len(short) > 0 and len(long) > 0:
- arg = "%s/%s%s" % (short.pop(), long.pop(), required)
+ arg = f"{short.pop()}/{long.pop()}{required}"
while len(short) > 0:
- arg = "%s/%s" % (short.pop(), required)
+ arg = f"{short.pop()}/{required}"
while len(long) > 0:
- arg = "%s%s" % (long.pop(), required)
+ arg = f"{long.pop()}{required}"
args.append(arg)
@@ -503,7 +481,7 @@ class FishCompletionWriter(ArgparseWriter):
# indicate that such subcommand exists.
args = " ".join(args)
- return "set -g %s %s\n" % (optspec_var, args)
+ return f"set -g {optspec_var} {args}\n"
@staticmethod
def complete_head(
@@ -524,12 +502,14 @@ class FishCompletionWriter(ArgparseWriter):
subcmd = s[1] if len(s) == 2 else ""
if index is None:
- return "complete -c %s -n '__fish_spack_using_command %s'" % (s[0], subcmd)
+ return f"complete -c {s[0]} -n '__fish_spack_using_command {subcmd}'"
elif nargs in [argparse.ZERO_OR_MORE, argparse.ONE_OR_MORE, argparse.REMAINDER]:
- head = "complete -c %s -n '__fish_spack_using_command_pos_remainder %d %s'"
+ return (
+ f"complete -c {s[0]} -n '__fish_spack_using_command_pos_remainder "
+ f"{index} {subcmd}'"
+ )
else:
- head = "complete -c %s -n '__fish_spack_using_command_pos %d %s'"
- return head % (s[0], index, subcmd)
+ return f"complete -c {s[0]} -n '__fish_spack_using_command_pos {index} {subcmd}'"
def complete(
self,
@@ -597,25 +577,18 @@ class FishCompletionWriter(ArgparseWriter):
if choices is not None:
# If there are choices, we provide a completion for all possible values.
- commands.append(head + " -f -a %s" % self._quote(" ".join(choices)))
+ commands.append(f"{head} -f -a {shlex.quote(' '.join(choices))}")
else:
# Otherwise, we try to find a predefined completion for it
value = _fish_dest_get_complete(prog, args)
if value is not None:
- commands.append(head + " " + value)
+ commands.append(f"{head} {value}")
return "\n".join(commands) + "\n"
def prog_comment(self, prog: str) -> str:
- """Return a comment line for the command.
-
- Args:
- prog: Program name.
-
- Returns:
- Comment line.
- """
- return "\n# %s\n" % prog
+ """Return a comment line for the command."""
+ return f"\n# {prog}\n"
def optionals(
self,
@@ -658,28 +631,28 @@ class FishCompletionWriter(ArgparseWriter):
for f in flags:
if f.startswith("--"):
long = f[2:]
- prefix += " -l %s" % long
+ prefix = f"{prefix} -l {long}"
elif f.startswith("-"):
short = f[1:]
assert len(short) == 1
- prefix += " -s %s" % short
+ prefix = f"{prefix} -s {short}"
# Check if option require argument.
# Currently multi-argument options are not supported, so we treat it like one argument.
if nargs != 0:
- prefix += " -r"
+ prefix = f"{prefix} -r"
if dest is not None:
# If there are choices, we provide a completion for all possible values.
- commands.append(prefix + " -f -a %s" % self._quote(" ".join(dest)))
+ commands.append(f"{prefix} -f -a {shlex.quote(' '.join(dest))}")
else:
# Otherwise, we try to find a predefined completion for it
value = _fish_dest_get_complete(prog, dest)
if value is not None:
- commands.append(prefix + " " + value)
+ commands.append(f"{prefix} {value}")
if help:
- commands.append(prefix + " -d %s" % self._quote(help))
+ commands.append(f"{prefix} -d {shlex.quote(help)}")
return "\n".join(commands) + "\n"
@@ -697,11 +670,11 @@ class FishCompletionWriter(ArgparseWriter):
head = self.complete_head(prog, 0)
for _, subcommand, help in subcommands:
- command = head + " -f -a %s" % self._quote(subcommand)
+ command = f"{head} -f -a {shlex.quote(subcommand)}"
if help is not None and len(help) > 0:
help = help.split("\n")[0]
- command += " -d %s" % self._quote(help)
+ command = f"{command} -d {shlex.quote(help)}"
commands.append(command)
@@ -747,7 +720,7 @@ def rst_index(out: IO) -> None:
for i, cmd in enumerate(sorted(commands)):
description = description.capitalize() if i == 0 else ""
- ref = ":ref:`%s <spack-%s>`" % (cmd, cmd)
+ ref = f":ref:`{cmd} <spack-{cmd}>`"
comma = "," if i != len(commands) - 1 else ""
bar = "| " if i % 8 == 0 else " "
out.write(line % (description, bar + ref + comma))
@@ -858,10 +831,10 @@ def _commands(parser: ArgumentParser, args: Namespace) -> None:
# check header first so we don't open out files unnecessarily
if args.header and not os.path.exists(args.header):
- tty.die("No such file: '%s'" % args.header)
+ tty.die(f"No such file: '{args.header}'")
if args.update:
- tty.msg("Updating file: %s" % args.update)
+ tty.msg(f"Updating file: {args.update}")
with open(args.update, "w") as f:
prepend_header(args, f)
formatter(args, f)