allow group_arguments to take a prefix length
Signed-off-by: Todd Gamblin <tgamblin@llnl.gov>
This commit is contained in:
parent
52ce977b93
commit
0b0cf998b4
@ -705,7 +705,11 @@ def first_line(docstring):
|
||||
|
||||
|
||||
def group_arguments(
|
||||
args: Sequence[str], max_group_size: int = 500, max_group_len: Optional[int] = None
|
||||
args: Sequence[str],
|
||||
*,
|
||||
max_group_size: int = 500,
|
||||
prefix_length: int = 0,
|
||||
max_group_length: Optional[int] = None,
|
||||
) -> Generator[List[str], None, None]:
|
||||
"""Splits the supplied list of arguments into groups for passing to CLI tools.
|
||||
|
||||
@ -722,30 +726,32 @@ def group_arguments(
|
||||
Arguments:
|
||||
args: list of arguments to split into groups
|
||||
max_group_size: max number of elements in any group (default 500)
|
||||
max_group_len: max length of characters that if a group of args is joined by " "
|
||||
prefix_length: length of any additional arguments to be passed before the groups from args;
|
||||
defaults to 0 characters.
|
||||
max_group_length: max length of characters that if a group of args is joined by " "
|
||||
On unix, ths defaults to SC_ARG_MAX from sysconf. On Windows the default is
|
||||
the max usable for CreateProcess (32,768 chars)
|
||||
|
||||
"""
|
||||
if max_group_len is None:
|
||||
max_group_len = 32768 # default to the Windows limit
|
||||
if max_group_length is None:
|
||||
max_group_length = 32768 # default to the Windows limit
|
||||
if hasattr(os, "sysconf"):
|
||||
# sysconf is only on unix and returns -1 if an option isn't present
|
||||
sysconf_max = os.sysconf("SC_ARG_MAX")
|
||||
if sysconf_max != -1:
|
||||
max_group_len = sysconf_max
|
||||
max_group_length = sysconf_max
|
||||
|
||||
group: List[str] = []
|
||||
grouplen, space = 0, 0
|
||||
grouplen, space = prefix_length, 0
|
||||
for i, arg in enumerate(args):
|
||||
arglen = len(arg)
|
||||
if arglen > max_group_len:
|
||||
if arglen > max_group_length:
|
||||
raise ValueError(f"Argument is longer than the maximum command line size: '{arg}'")
|
||||
|
||||
next_grouplen = grouplen + arglen + space
|
||||
if len(group) == max_group_size or next_grouplen > max_group_len:
|
||||
if len(group) == max_group_size or next_grouplen > max_group_length:
|
||||
yield group
|
||||
group, grouplen, space = [], 0, 0
|
||||
group, grouplen, space = [], prefix_length, 0
|
||||
|
||||
group.append(arg)
|
||||
grouplen += arglen + space
|
||||
|
@ -186,7 +186,8 @@ def pkg_grep(args, unknown_args):
|
||||
return 0 # no packages to search
|
||||
|
||||
# set up iterator and save the first group to ensure we don't end up with a group of size 1
|
||||
groups = spack.cmd.group_arguments(all_paths)
|
||||
prefix_length = len(" ".join(args.grep_args + unknown_args))
|
||||
groups = spack.cmd.group_arguments(all_paths, prefix_length=prefix_length)
|
||||
|
||||
# You can force GNU grep to show filenames on every line with -H, but not POSIX grep.
|
||||
# POSIX grep only shows filenames when you're grepping 2 or more files. Since we
|
||||
|
@ -322,7 +322,7 @@ def test_pkg_hash(mock_packages):
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
["max_group_size", "max_group_len", "lengths", "error"],
|
||||
["max_group_size", "max_group_length", "lengths", "error"],
|
||||
[
|
||||
(3, 1, None, ValueError),
|
||||
(3, 13, None, ValueError),
|
||||
@ -334,9 +334,9 @@ def test_pkg_hash(mock_packages):
|
||||
(4, 56, [4, 4, 2], None),
|
||||
],
|
||||
)
|
||||
def test_group_arguments(mock_packages, max_group_size, max_group_len, lengths, error):
|
||||
def test_group_arguments(mock_packages, max_group_size, max_group_length, lengths, error):
|
||||
generator = spack.cmd.group_arguments(
|
||||
group_args, max_group_size=max_group_size, max_group_len=max_group_len
|
||||
group_args, max_group_size=max_group_size, max_group_length=max_group_length
|
||||
)
|
||||
|
||||
# just check that error cases raise
|
||||
@ -349,7 +349,7 @@ def test_group_arguments(mock_packages, max_group_size, max_group_len, lengths,
|
||||
assert sum(groups, []) == group_args
|
||||
assert [len(group) for group in groups] == lengths
|
||||
assert all(
|
||||
sum(len(elt) for elt in group) + (len(group) - 1) <= max_group_len for group in groups
|
||||
sum(len(elt) for elt in group) + (len(group) - 1) <= max_group_length for group in groups
|
||||
)
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user